はなちるのマイノート

Unityをメインとした技術ブログ。自分らしくまったりやっていきたいと思いますー!

【Rider】nullになることを示す[CanBeNull]・ならないことを示す[NotNull] と 値解析モードによる挙動の違いについて

はじめに

今回は[CanBeNull][NotNull]、またそれらに対する挙動を設定できる値解析モードについて取り上げたいと思います。

pleiades.io

// 値解析モードによる挙動の違いについてのサンプル
var sample = new Sample(canBeNullObj: null, notNullObj: null, obj: null);

// 値解析モードが楽観的・悲観的のどちらでも警告が出てくる
var canBeNullObj = sample.CanBeNullObj;
_ = canBeNullObj.ToString();

// 値解析モードが楽観的・悲観的のどちらでも警告は出てこない
var notNullObj = sample.NotNullObj;
_ = notNullObj.ToString();

// 楽観的だと警告が出ない, 悲観的だと警告が出てくる
var obj = sample.Obj;
_ = obj.ToString();

概要

CanBeNull属性とNotNull属性については以下の通り。

属性 意味
[CanBeNull] nullになる可能性あり
[NotNull] nullにならない

[CanBeNullAttribute]
マークされた要素の値が null になることがあることを示します。そのため、使用前に null のチェックが必要です。

[NotNullAttribute]
マークされた要素の値が決して null でないことを示します。

コードアノテーション属性 | ReSharper ドキュメント

public class Sample
{
    public Sample([CanBeNull] object canBeNullObj, [NotNull] object notNullObj)
    {
        CanBeNullObj = canBeNullObj;
        NotNullObj = notNullObj;
    }

    [CanBeNull]
    public object CanBeNullObj { get; }

    [NotNull]
    public object NotNullObj { get; }
}

値解析モードによるRiderの挙動の違い

Riderには値解析モードなるものが設定に用意されており、楽観的悲観的 によって挙動が変わります。

設定 -> インスペクション設定 -> 値解析モード

楽観的
デフォルトでは、値分析モードは楽観的です。このモードでは、値が NULL 可能性について明示的にチェックされた場合、またはシンボルが [CanBeNull] または [ItemCanBeNull] 属性でマークされている場合に限り、JetBrains Rider は可能な 'null' 参照を警告します。楽観的モードは上記の例で示されています。

悲観的な
このモードでは、シンボルが [NotNull] または [ItemNotNull] 属性でマークされていない限り、JetBrains Rider は値が NULL 可能性について明示的にチェックされていないすべてのコンテキストで可能な 'null' 参照を警告します。

pleiades.io

違いとしては楽観的だと[CanBeNull]が付いている値のみに警告をだすのに対し、悲観的だと[NotNull]がついていないと警告を出すようになります。

public class Sample
{
    private void Main()
    {
        var sample = new Sample(canBeNullObj: null, notNullObj: null, obj: null);

        // 楽観的・悲観的のどちらでも警告が出てくる
        var canBeNullObj = sample.CanBeNullObj;
        _ = canBeNullObj.ToString();

        // 楽観的・悲観的のどちらでも警告は出てこない
        var notNullObj = sample.NotNullObj;
        _ = notNullObj.ToString();

        // 楽観的だと警告が出ない, 悲観的だと警告が出てくる
        var obj = sample.Obj;
        _ = obj.ToString();
    }

    public Sample([CanBeNull] object canBeNullObj, [NotNull] object notNullObj, object obj)
    {
        CanBeNullObj = canBeNullObj;
        NotNullObj = notNullObj;
        Obj = obj;
    }

    [CanBeNull]
    public object CanBeNullObj { get; }

    [NotNull]
    public object NotNullObj { get; }
    
    public object Obj { get; }
}
楽観的
悲観的