情報応用演習Ⅰ(2024)

【T2b】新しいNull許容/非許容型(6/6)

プロジェクトタイプC#コンソールアプリ※
プロジェクト名T2b
ソリューション名PIT2
ターゲットフレームワーク.NET 8.0(長期的なサポート)
最上位レベルのステートメントを使用しない使用する(チェックオフ)

※「コンソールアプリ(.NET Framework)」ではないので注意せよ!

注意
  • 本ページの作業内容は 前のページまでの続き になっていることに注意せよ.
    • 先に前のページまでをすべて読み,指示されている作業を済ませてから本ページを読むこと.
    • プロジェクトの作成作業についてはNull許容参照型を参照せよ.

2b-6. null免除演算子

最後に null チェックにまつわる少し厄介な演算子─null免除演算子について説明しておこう.

前々節で,C#コンパイラはプログラムの流れを追跡してNull許容ではない通常の参照型に対する null の代入といった操作を警告する,と書いたが 実はこの追跡がうまくいかないケースもある.というよりも実行していないプログラムの実行結果を,機械的に正確に予想するのは原理的に不可能なので, null 代入の追跡は限定された場面でしかうまく機能しない,あくまでも助言的な機能であると理解しておくべきである.

このことを確かめてみよう,Program.csの Studentクラスの定義の直前に _に示すメソッドを追記しよう.

(NO CAPTION)
1
2
3
4
static string? GetSomeValue() 
{
    return "本日は晴天なり.";
}

このGetSomeValue()メソッド自体は特に意味のある動作をしているわけではないが,注目するべきは戻り値型実際の戻り値である. このメソッドの戻り値型は string? 型,つまりNull許容な string 型である.そしてメソッドの処理内容を見ると,return文で無条件で "本日は晴天なり." という内容固定の文字列定数を返却している.したがってこのメソッドから null が返却されることは絶対にない

ではこのメソッドの戻り値を,Null許容ではない普通の string 型の変数に代入するとどうなるだろうか. ためしにリスト2b-4-2で定義した変数barにこのメソッドの戻り値を代入してみよう.Program.csに_に示す内容を追記する.

Program.csの変更内容
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
string? hoge = null;

Console.WriteLine(hoge);

int? piyo = null;

if (piyo.HasValue)
{
    Console.WriteLine(piyo.Value);
}

if (hoge != null)
{
    Console.WriteLine(hoge);
}

int foo = 0;

if (piyo != null)
{
    foo = piyo.Value;
}

string bar = "xyzzy";

if (hoge != null)
{
    bar = hoge;
}

bar = GetSomeValue();

static string? GetSomeValue() 
{
    return "本日は晴天なり.";
}

class Student
{
    public int ID { get; set; }

    public string Name { get; set; } = "xyzzy";
                                                
    public DateTime Birthday { get; set; }
}

すると_に示す通り警告が表示されてしまうはずである.

記述結果

このように,プログラマーにはその文脈で絶対に null が代入されないことは分かっている場合でも, コンパイラには実行時の挙動は完全に追跡できないため警告が表示されてしまうケースは多々ある. このような場合には次のようにすると警告を抑止することができる.Program.csを_に示す通りに修正する.

Program.csの変更内容
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
string? hoge = null;

Console.WriteLine(hoge);

int? piyo = null;

if (piyo.HasValue)
{
    Console.WriteLine(piyo.Value);
}

if (hoge != null)
{
    Console.WriteLine(hoge);
}

int foo = 0;

if (piyo != null)
{
    foo = piyo.Value;
}

string bar = "xyzzy";

if (hoge != null)
{
    bar = hoge;
}

bar = GetSomeValue()!; // 後置 ! 演算子(null免除演算子)をつければ警告は出ない.

static string? GetSomeValue() 
{
    return "本日は晴天なり.";
}

class Student
{
    public int ID { get; set; }

    public string Name { get; set; } = "xyzzy";
                                                
    public DateTime Birthday { get; set; }
}

すると今度は_に示す通り警告は表示されないはずである.

記述結果

この後置した!記号は, null免除演算子 あるいは null抑制演算子 といい,nullになりうる式!のようにして式の後ろに書くことで null 代入に関する警告を抑制することができる.

ただしこれは みだりに使用するべきではない という点には注意しておこう.重要なことなのでもう一度書いて強調するが, null免除演算子はみだりに使用するべきではない.前述したように,そもそも参照型にも Null許容/非許容の概念が押し広げられたのはnullの関与する操作における誤りを低減するためである.しかし,null免除演算子はそのチェックをだまくらかす手段になってしまう ので 本当に必要な場面以外では使用するべきではない.nullを使用するのであれば,nullに対する操作が発生しないようなコード設計をするべきである.

ここまでの内容を理解したら二つ目のチュートリアルは完了である. 以降の作業における混乱を防ぐため,次に進む前に Visual Studio のエディタをすべて閉じておこう.Visual Studio のいずれかのエディタのタブを右クリックして 「すべてのドキュメントを閉じる」をクリックすれば,エディタをすべて閉じることができる

Last updated on 2024-04-26
Published on 2024-04-26

Powered by Hugo. Theme by TechDoc. Designed by Thingsym.