# Null 参照

> Understand what causes a NullReferenceException in C# and how to avoid uninitialized object references.

C# で値が `null` 型のメンバーにアクセスしようとすると、`NullReferenceException` が発生します。ランタイムの `NullReferenceException` は、多くの場合、オブジェクトリファレンス変数を、使用する前に初期化しなかったことを意味します。null 参照が発生する一般的なコーディングエラーの詳細については、[Microsoft のドキュメント](https://learn.microsoft.com/en-us/dotnet/api/system.nullreferenceexception?view=net-8.0)を参照してください。

null 参照のエラーメッセージは次のようになります。

```
NullReferenceException: Object reference not set to an instance of an object
    at Example.Start () [0x0000b] in /Unity/projects/nre/Assets/Example.cs:10 
```

このエラーメッセージは、スクリプトファイル `Example.cs` の 10 行目で `NullReferenceException` が生じ、`Start()` 関数の内部で例外が発生したことを示しています。これで Null Reference Exception の検出と修正が容易になります。この例では以下のようなコードになります。

```lang-csharp
using UnityEngine;
using System.Collections;

public class Example : MonoBehaviour {

    // Use this for initialization
	void Start () {
		GameObject myGameObject = GameObject.Find("exampleGameObject");
    	Debug.Log(myGameObject.name);
    }
	
}
```

コードは "exampleGameObject" というゲームオブジェクトを探します。この例では、同じ名前のゲームオブジェクトがないので、`Find()` 関数は `null` を返します。スクリプトは次の行 (9 行目) で `myGameObject` 変数を使用し、参照するゲームオブジェクトの名前を出力します。存在しないゲームオブジェクトにアクセスしようとしているため、`NullReferenceException` が返されます。

## Null checks

この例でのソリューションは、指定された名前のゲームオブジェクトが存在しない場合の結果を追加することです。以下のスクリプトは、`go` 変数が `null` を返すかどうかを確認し、返す場合はメッセージを表示します。

```lang-csharp
using UnityEngine;
using System.Collections;

public class Example : MonoBehaviour {

    void Start () {
	    GameObject myGameObject = GameObject.Find("exampleGameObject");
		if (myGameObject == null) {
			Debug.Log("No GameObject called exampleGameObject found");
    	} else {
			Debug.Log(myGameObject.name);
    	}
    }
    	
}
```

### カスタムの == 演算子

[UnityEngine.Object](/engine/6000.0/manual/scripting/get-started/fundamental-unity-types/class-object.md) から継承する型の場合、Unity では C# の[等式演算子および不等式](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/equality-operators)のカスタム版が使用されます。つまり、前の例 (`myGameObject == null`) の null チェックは、技術的には `myGameObject` が有効な C# オブジェクトリファレンスを保持していても、`true` を評価できます (また、逆に `myGameObject != null` は `false` を評価できます)。これは 2 つのケースで発生します。

1. オブジェクトが、いわゆる "fake null" またはプレースホルダーオブジェクトの場合。これは、Unity では初期化されていない MonoBehaviour フィールドに入力するためにのみ、エディターで使用されます。これらのオブジェクトは、フィールドをリファレンスしようとしたときに、そのソースを見つけるために役立つデバッグ情報を格納します。
2. オブジェクトが、まだガベージコレクションされていないマネージ (C#) オブジェクトである可能性があるものの、アンマネージ (C++) のオブジェクトが破棄されているために、null と見なす必要がある場合。

## Try/Catch ブロック

**Inspector** ウィンドウで初期化が必要な変数を使用する場合も、`NullReferenceException` を呼び出します。初期化しなかった場合、その変数は `null` になります。`NullReferenceException` を処理するもうひとつの方法は、`try`/`catch` ブロックを使用することです。 例:

```lang-csharp
using UnityEngine;
using System;
using System.Collections;

public class Example2 : MonoBehaviour {

    public Light myLight; // set in the inspector
	
	void Start () {
		try {
			myLight.color = Color.yellow;
    	}		
    	catch (NullReferenceException ex) {
	    	Debug.Log("myLight was not set in the inspector");
		}
	}
	
}
```

このコード例では、`myLight` という変数は `Light` で、Inspector ウィンドウで設定する必要があります。この変数が設定されていない場合は、デフォルトで `null` になります。

`try` ブロックのライトの色を変更しようとすると、`NullReferenceException` が発生します。この場合、`catch` ブロックコードによって、Inspector でライトを設定するように促すメッセージが表示されます。

## 追加リソース

* [UnityEngine.Object](/engine/6000.0/manual/scripting/get-started/fundamental-unity-types/class-object.md)
