いくつ知ってる?C# 便利なnullエラー回避テクニック

2023年11月1日水曜日

C#

t f B! P L

enter image description here

いわゆるnull 参照エラー(一部では「ヌルポエラー」とも言われる)は、プログラムのバグの原因でもっとも多い問題の一種です。プログラマーにとって天敵とも言える存在かもしれません。
しかし、C#には null 参照エラーをスマートに解決するためのシンタックスシュガー(糖衣構文)があります。
この記事では、C#で null 参照をスマートに実装する構文を紹介します。

スポンサーリンク

そもそも、なんでnullが必要なの?

null は古くからあるプログラミング言語に取り入れられている概念です。
すべてのプログラマーにとって null はお友達みたいなものです。(違う?)
しかし、null のせいで障害が発生するなら、いっそのこと null という概念自体を無くしてしまえと思った人も少なくないでしょう。
実際にObjective-Cのようなプログラミング言語では、null の変数に対して関数を呼び出しても、例外を発生させない仕様が採用されましたが、あまり受け入れられませんでした。

null は重要な概念!nullとうまく付き合う

nullはプログラミングにおける重要な概念で、特定の状態や条件を明示的に表現するのに役立ちます。たとえば、オプショナルな値を扱ったり、エラーや異常状態を示したり、未初期化の状態を表現したりする際にはnullが利用されます。一方で、nullを適切に扱わないと null 参照エラーが発生し、プログラムの安定性に影響を与える可能性があります。しかし、このようなエラーは、適切な null チェックやエラー処理を行うことで防ぐことができます。nullはコードの意図を明確に伝え、プログラムのロジックを簡潔に保つために不可欠な要素であり、それを理解し適切に扱うことは、安全で効率的なコードを書くために重要です。

前置きが長くなってしまいました。次からC#で null をスマートに扱う方法を紹介します。

null許容型

C#でプログラミングする上で、null許容型の知識は必須です。
null許容型は、値型(int, double, boolなど)の変数が null 値を持つことができるようにする特別な型です。これは、?修飾子を使用して宣言されます。
C#では、このnull許容型によってあらゆる型の変数に null を代入可能です。

int? num;  //`?`修飾子で宣言された変数には初期値にnullが入る

null許容型のメリット

null許容型のメリットを3つ挙げましょう。

未初期化の状態を明示できる

null許容型を使用することで、変数がまだ値を持っていない状態を明示できます。

通常の値型では、例えばintの場合は「0」、DateTimeの場合は「0001/01/01」といったデフォルトの初期値が設定されます。しかし、これらの初期値が意図的に設定されたのか、それとも単に未初期化のデフォルト値なのかを区別するのは困難です。 対して、null許容型は null 値を利用して未初期化状態を明示的に表現することができます。

参照型でもnull許容型を利用できる

?修飾子を利用することで、参照型の変数でもnull許容型を宣言することが可能です。

参照型では、null許容型の導入前から以下のように変数にnullを設定することができました。

Person person = null;

しかし、プログラムが複雑化すると、変数がnullの値を取り得るかどうかを判断するのが困難になります。これにより、if (person != null) のようにnull参照エラーを避けるための分岐処理が頻繁に登場し、コードの可読性が低下することがありました。
?修飾子を使って参照型のnull許容型を宣言することで、変数がnull値を取り得る可能性を明示できます。これにより、不必要なnull判定のロジックを削減し、コードの可読性と管理性を向上させることができます。

データベースの連携がしやすい

データベースとのやり取りにおいて、特定のフィールドが値を持っていない(つまりNULL)ことを示す必要があります。C#のnull許容型は、データベースのNULL値を適切に表現し、ハンドルするのに役立ちます。これにより、データベースとの連携がより簡単かつ効果的に行えます。

null条件演算子

null条件演算子を使って、オブジェクトが null でない場合にのみメソッドを呼び出すことができます。これは、プログラムの安全性を向上させ、null参照例外を防ぐのに役立ちます。

以下は、null条件演算子の使用方法です。

Person? person = new Person();
person = null;
var result = person?.SayHello();   // result = null

上記のコードでは、personオブジェクトがnullでない場合にのみ、SayHelloメソッドが呼び出されます。personnull の場合、?.演算子はnullを返し、SayHelloメソッドは呼び出されません。

null条件演算子は、インデクサアクセスにも使用可能です。
次のコードは、collectionオブジェクトが null の場合、インデクサアクセスはスキップされ null が返却されます。

StringCollection collection = null;
var item = collection?[1];

null合体演算子

この演算子は、変数が null であるかどうかをチェックし、null でない場合はその値を、null の場合は別のデフォルト値を返します。これにより、プログラマーは null 参照エラーに関する問題をスマートに解決できます。

以下は「null 合体演算子」の基本的な使い方の例です。
変数 anull であるため、?? の右側に書いたデフォルト値が返ります。

int? a = null;
int b = a ?? 0;  // aがnullなので、bは0になります

スポンサーリンク

null合体代入演算子

null 合体代入 (??=) が導入されました。これにより、変数が null の場合にのみ値を代入することができます。
「null 合体演算子」よりも、代入処理はスッキリ書けます。

string name1 = null;
name1 ??= "foo";  // name1がnullなので、"foo"が代入されます

string name2 = "bar";
name2 ??= "foo";  // name2にはnull以外の値が設定済みのため、代入されず値は"bar"のままです。

まとめ

C#でnull 参照エラーを回避し、nullとうまく付き合うための糖衣構文を紹介してきました。
この記事では、次のことを紹介しています。

  • nullは未初期化を表す重要な概念である。nullをうまく使ったプログラミングを心がけよう
  • C#には「null許容型」「null条件演算子」「null合体演算子」などの便利な型や糖衣構文が存在する
スポンサーリンク
スポンサーリンク

このブログを検索

Profile

自分の写真
Webアプリエンジニア。 日々新しい技術を追い求めてブログでアウトプットしています。
プロフィール画像は、猫村ゆゆこ様に書いてもらいました。

仕事募集もしていたり、していなかったり。

QooQ