かきスタンプ

福岡でフリーランスの物流系のエンジニアやってます。

C#:アップキャストとダウンキャストについて、サンプルソース付きで解説してみる

f:id:kakisoft:20180429085405p:plain

  • アップキャストは、常に安全に行える
  • ダウンキャストは、エラーが発生する事がある。  
     
※ 解説 ※
  • キャストは型を変更するだけで、中身が消える訳ではない。
    (アクセスできる範囲が変わるだけで、実態は存在している)
  • インスタンス作成時、メモリに領域が割り当てられる。
  • 子クラスのインスタンスは、親クラスのインスタンスより多くの領域を必用とする。
  • 親→子 とキャストした場合、子クラスが必要とする領域に、メモリが割り当てられていない状態となる。
    (そのため、エラーとして弾いている。)

 
 
以上を踏まえて、サンプルソースで説明。

//親クラス
class ParentClass { }
//子クラス
class ChildClass : ParentClass { }

private void MyButton01_Click()
{
    //===========================
    //      アップキャスト
    //===========================
    ParentClass parent01;
    ChildClass child01;

    //子クラスのインスタンスを生成
    child01 = new ChildClass();

    //子クラスのインスタンスを、親クラスに代入可能。
    parent01 = child01;


    //===========================
    //  ダウンキャスト(エラー)
    //===========================
    ParentClass parent02;
    ChildClass child02;

    //親クラスのインスタンスを生成
    parent02 = new ParentClass();

    //キャストできるかどうか確認(falseになります)
    if (parent02 is ChildClass)
    {
        //キャスト時にエラーが発生する
        child02 = (ChildClass)parent02;
    }

    //asを使えば キャストできない場合 nullが入る
    child02 = parent02 as ChildClass;


    //===========================
    //     ダウンキャスト
    //===========================
    ParentClass parent03;
    ChildClass child03;

    //親クラスのインスタンスを、子クラスで生成
    parent03 = new ChildClass();

    //ダウンキャスト可。
    child03 = (ChildClass)parent03;
}

C#:ネット上で一番簡単な、async/await を使用した非同期処理の説明とサンプル

非同期処理にて使用する async/await の超簡単な説明

  • 非同期メソッドには async キーワードを付ける。
  • 呼び出し先が async void の場合、呼び出し元に awaitは不要
  • 呼び出し先が async Task の場合、呼び出し元に awaitを記述する。
  • Task<T> は T の型が返る。(例:Task<string> は string が返る)
  • Task で取得した値を取り出すには、await を使用する。
  • 非同期メソッドの末尾は「Async」とする(慣習)

 
 
以下、ボタンを押したら google.co.jp の内容を取得するプログラムです。
フォーム側は WPFWindows Forms あたりで適当に用意して下さい。

サンプルコード

private void Button01_Click(object sender, RoutedEventArgs e)
{
    //呼び出し先が async void の場合、呼び出し元に awaitは不要
    Button01_ClickContentAsync(); 
}
//非同期メソッドには async キーワードを付ける。
private async void Button01_ClickContentAsync() 
{
    string targetURL = "http://www.google.co.jp/";

    //呼び出し先が async Task の場合、呼び出し元に awaitを記述する。
    await HttpGetRequestAsync(targetURL); 
}

private async Task HttpGetRequestAsync(string targetURL)
{
    using (var _httpClient = new HttpClient())
    {
        //Task<string> は string が返る
        Task<string> response = _httpClient.GetStringAsync(targetURL); 
        //Task で取得した値を取り出すには、await を使用する。
        string contents = await response; 

        Console.WriteLine(contents);
    }
}

 
初めのうちは、「async」って何?(Microsoft Docsを読む)、「await」って何?(Microsoft Docsを読む)、「Task」って(略)
・・・と、構文1つ1つを調べながら進めていくより、『非同期処理にて使用する構文』と、ひとまとめにして読み進める方が、理解しやすいんじゃないかと思います。  
 
 
非同期処理について調べていると、ディープな世界に踏み込んでいったり、過去の歴史まで遡りながら解説しているサイトが多く、
「理論は後でちゃんと学ぶから、まず、どんなコード書けばいいの?」という人向けの記事が少ないなー、と思ったんで、エントリにしてみた。

WPF:Grid上の好きなポジションに、動的に要素を配置

System.Windows.Controls.Grid は、Grid.Row と Grid.Column にて、要素のポジションを指定します。
 
動的に要素を配置する場合、SetValue にて、Grid.RowProperty と Grid.ColumnProperty を設定するとOKです。

実行例

f:id:kakisoft:20180410001143p:plain

ソース

xaml

<Window x:Class="PracticeWPF.MyWindow19"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:PracticeWPF"
        mc:Ignorable="d"
        Title="MyWindow19" Height="200" Width="200">
    <Grid>
        <Grid x:Name="myGrid01" Width="150" Height="150">
            <Grid.RowDefinitions>
                <RowDefinition Height="1*"/>
                <RowDefinition Height="1*"/>
                <RowDefinition Height="1*"/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1*"/>
                <ColumnDefinition Width="1*"/>
                <ColumnDefinition Width="1*"/>
            </Grid.ColumnDefinitions>
        </Grid>
    </Grid>
</Window>

cs側

using System.Windows;
using System.Windows.Controls;

namespace PracticeWPF
{
    /// <summary>
    /// Gridの指定位置に要素を追加
    /// </summary>
    public partial class MyWindow19 : Window
    {
        public MyWindow19()
        {
            InitializeComponent();

            SetGridItems();
        }

        private void SetGridItems()
        {
            Button b0_0 = new Button();
            b0_0.Content = "0-0";
            b0_0.SetValue(Grid.RowProperty, 0);
            b0_0.SetValue(Grid.ColumnProperty, 0);
            myGrid01.Children.Add(b0_0);

            Button b0_2 = new Button();
            b0_2.Content = "0-2";
            b0_2.SetValue(Grid.RowProperty, 0);
            b0_2.SetValue(Grid.ColumnProperty, 2);
            myGrid01.Children.Add(b0_2);

            Button b1_1 = new Button();
            b1_1.Content = "1-1";
            b1_1.SetValue(Grid.RowProperty, 1);
            b1_1.SetValue(Grid.ColumnProperty, 1);
            myGrid01.Children.Add(b1_1);

            Button b2_2 = new Button();
            b2_2.Content = "2-2";
            b2_2.SetValue(Grid.RowProperty, 2);
            b2_2.SetValue(Grid.ColumnProperty, 2);
            myGrid01.Children.Add(b2_2);
        }
    }
}

WPF:動的に配置したボタンにイベントを定義

WPFC#)で、ボタンを動的に配置し、イベントを定義する方法。

実行例

f:id:kakisoft:20180404222601p:plain

※ボタンはソース側にて、動的に配置しています。

ボタンを押したときのイベント内容

dynamicButton01がクリックされました。
dynamicButton02がクリックされました。
(記述例)

xaml

<Window x:Class="PracticeWPF.MyWindow14"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:PracticeWPF"
        mc:Ignorable="d"
        Title="MyWindow14" Height="450" Width="800">
    <Grid>
        <StackPanel x:Name="myStackPanel01"  Width="500" Orientation="Horizontal"  HorizontalAlignment="Left" VerticalAlignment="Top" >
        </StackPanel>
    </Grid>
</Window>

cs側

using System;
using System.Windows;
using System.Windows.Controls;

namespace PracticeWPF
{
    /// <summary>
    /// 動的に配置したボタンにイベントを定義
    /// </summary>
    public partial class MyWindow14 : Window
    {
        public MyWindow14()
        {
            InitializeComponent();

            SetButtonDynamicEvent();
        }
        private void SetButtonDynamicEvent()
        {
            Button b1 = new Button();
            b1.Content = "Dynamic Button01";
            b1.Name = "b1";
            b1.Click += (sender, e) => ButtonDynamicEvent(sender);
            myStackPanel01.Children.Add(b1);

            Button b2 = new Button();
            b2.Content = "Dynamic Button02";
            b2.Name = "b2";
            b2.Click += (sender, e) => ButtonDynamicEvent(sender);
            myStackPanel01.Children.Add(b2);
        }

        private void ButtonDynamicEvent(object sender)
        {
            Console.WriteLine(((Button)sender).Name + "がクリックされました。");
        }
    }
}

WPF:ボタンのテキストで改行させる

WPFにて、ボタンのテキストを改行して表示させる場合、TextBlock を入れ子にする方法があります。
xaml側、cs側の、どちらでも対応可能です。

(実行例)

f:id:kakisoft:20180402221750p:plain

(記述例)

xaml

<Window x:Class="PracticeWPF.MyWindow10"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:PracticeWPF"
        mc:Ignorable="d"
        Title="MyWindow10" Height="450" Width="800">
    <Grid>
        <!--
        ==========< ボタン内で改行を入れる >==========
        -->
        <StackPanel Width="500" Orientation="Horizontal"  HorizontalAlignment="Left" VerticalAlignment="Top" >
            <!-- xaml側で実現  -->
            <Button>
                <TextBlock x:Name="InnerTextBlock01" TextWrapping="Wrap" Text="ButtonにTextBlockを入れ子にできるよ。" Width="80" />
            </Button>

            <!-- cs側で実現(csソース参照)  -->
            <Button x:Name="Button02"  Content="" Width="80"/>
        </StackPanel>

    </Grid>
</Window>

cs側

using System.Windows;
using System.Windows.Controls;

namespace PracticeWPF
{
    /// <summary>
    /// MyWindow10.xaml の相互作用ロジック
    /// </summary>
    public partial class MyWindow10 : Window
    {
        public MyWindow10()
        {
            InitializeComponent();


            //==========< ボタン内で改行を入れる >==========
            //(コード側で設定)
            var b = new TextBlock();
            b.Text = "TexoBlockのTextWrappingを使うと改行が楽だよ。";
            b.TextWrapping = TextWrapping.Wrap;
            Button02.Content = b;
        }
    }
}

Oracle:大文字/小文字 半角/全角 ひらがな/カタカナ を区別しないで検索

以下の関数を組み合わせて、大文字/小文字 半角/全角 ひらがな/カタカナ を区別せずに検索できます。

  • UPPER(小文字→大文字)
  • TO_MULTI_BYTE(半角→全角)
  • UTL_I18N.TRANSLITERATE(詳細は後述)

(例)
以下で、「大文字・全角・カタカナ」に変換しています。

--('target_character' が、検索対象文字です。)
UTL_I18N.TRANSLITERATE(UPPER(TO_MULTI_BYTE('target_character')),'kana_fwkatakana')

SQL出力例

CHAR

select
    UTL_I18N.TRANSLITERATE(UPPER(TO_MULTI_BYTE('a')) ,'kana_fwkatakana') as S1 -- 半角:a
   ,UTL_I18N.TRANSLITERATE(UPPER(TO_MULTI_BYTE('A')) ,'kana_fwkatakana') as S2 -- 半角:A
   ,UTL_I18N.TRANSLITERATE(UPPER(TO_MULTI_BYTE('')),'kana_fwkatakana') as S3 -- 全角:a
   ,UTL_I18N.TRANSLITERATE(UPPER(TO_MULTI_BYTE('')),'kana_fwkatakana') as S4 -- 全角:A
   ,UTL_I18N.TRANSLITERATE(UPPER(TO_MULTI_BYTE('')),'kana_fwkatakana') as S5 -- 全角:あ
   ,UTL_I18N.TRANSLITERATE(UPPER(TO_MULTI_BYTE('')),'kana_fwkatakana') as S6 -- 全角:ア
   ,UTL_I18N.TRANSLITERATE(UPPER(TO_MULTI_BYTE('')) ,'kana_fwkatakana') as S7 -- 半角:ア
from
    dual

<出力結果>

S1 S2 S3 S4 S5 S6 S7

NVARCHAR2
NVARCHAR2の場合、「半角→全角」への変換が上手く行かないので、to_charをかましてます。

select
    UTL_I18N.TRANSLITERATE(UPPER(TO_MULTI_BYTE(to_char(substr(COL1,1,1)))),'kana_fwkatakana') as V1 -- 半角:b
   ,UTL_I18N.TRANSLITERATE(UPPER(TO_MULTI_BYTE(to_char(substr(COL2,1,1)))),'kana_fwkatakana') as V2 -- 半角:B
   ,UTL_I18N.TRANSLITERATE(UPPER(TO_MULTI_BYTE(to_char(substr(COL3,1,1)))),'kana_fwkatakana') as V3 -- 全角:b
   ,UTL_I18N.TRANSLITERATE(UPPER(TO_MULTI_BYTE(to_char(substr(COL4,1,1)))),'kana_fwkatakana') as V4 -- 全角:B
   ,UTL_I18N.TRANSLITERATE(UPPER(TO_MULTI_BYTE(to_char(substr(COL5,1,1)))),'kana_fwkatakana') as V5 -- 全角:い
   ,UTL_I18N.TRANSLITERATE(UPPER(TO_MULTI_BYTE(to_char(substr(COL6,1,1)))),'kana_fwkatakana') as V6 -- 全角:イ
   ,UTL_I18N.TRANSLITERATE(UPPER(TO_MULTI_BYTE(to_char(substr(COL7,1,1)))),'kana_fwkatakana') as V7 -- 半角:イ
from
    (
       select
            CAST('b: 半角'  as NVARCHAR2(100)) as COL1
           ,CAST('B: 半角'  as NVARCHAR2(100)) as COL2
           ,CAST('b: 全角' as NVARCHAR2(100)) as COL3
           ,CAST('B: 全角' as NVARCHAR2(100)) as COL4
           ,CAST('い: 全角' as NVARCHAR2(100)) as COL5
           ,CAST('イ: 全角' as NVARCHAR2(100)) as COL6
           ,CAST('イ: 全角'  as NVARCHAR2(100)) as COL7
       from
           dual
    ) TMP_VIEW01

<出力結果>

V1 V2 V3 V4 V5 V6 V7

UTL_I18N.TRANSLITERATE にて使用できる変換文字列

変換名文字列 説明
'kana_fwkatakana' 全角カタカナに変換
'kana_hwkatakana' 半角カタカナに変換
'kana_hiragana' 全角ひらがなに変換
'fwkatakana_hwkatakana' 全角カタカナのみを半角カタカナに変換
'fwkatakana_hiragana' 全角カタカナのみを全角ひらがなに変換
'hwkatakana_fwkatakana' 半角カタカナのみを全角カタカナに変換
'hwkatakana_hiragana' 半角カタカナのみを全角ひらがなに変換
'hiragana_fwkatakana' 全角ひらがなのみを全角カタカナに変換
'hiragana_hwkatakana' 全角ひらがなのみを半角カタカナに変換

Oracle12:【忙しい人向け】ユーザ作成方法

Oracle12にて、以下のようなメッセージが出てユーザが作成できなかった時の対処。

【エラーメッセージ】
ORA-65096: 共通ユーザーまたはロール名が無効です

ググったら、何やら複雑な情報がバシバシと出てくるけど、要は「12からアーキテクチャが変わった」のが原因。
 
 
SYSDBAにて接続後、以下のコマンドを、中身変えずにそのまま実行します。

プラガブルデータベース起動

alter pluggable database orclpdb open;

現在のコンテナをプラガブルデータベースに変更

alter session set container = orclpdb;

 
後は、通常通りCREATE USER で。
途中で出てくる「orclpdb」は、インストール時のデフォルト値です。
深い事を考えず「次へ」「次へ」でインストールした場合は、この値になっているかと思います。
 
 
 
この記事は、
「この問題を解決するためには、まずはアーキテクチャから理解しなければいけません。まずは、(長々とした説明)」
とか出てきて、  
『いや、Oracle様の高尚なアーキテクチャの説明はいいから、まずは目の前の問題を解決するコマンド教えてくれよ。
 ややこしい話は、家でビール飲みながらゆっくり見るから!
 
って思った人に向けて書いたエントリです。