2

次のクラス定義を考えてみましょう。

public class MyClass<T>
{
    public T t;
    public bool? c1(T obj) => obj?.Equals(null);
    public bool? c2() => t?.Equals(null);
}

結局のところ、いくつかのメモ:

  • MyClass<T>Tタイプに関する制約を課さないため、 Taclassまたは a struct;
  • c2() == c1(t)常に真でなければなりません。
  • http://tryroslyn.azurewebsites.net/サイトを使用して、いくつかのコード スニペットをコンパイルし、Roslyn が出力するものを確認しています。

それでは、Roslyn のコンパイル方法を分析してみましょうMyClass<T>

1.) c1(T)ケース:

予想通り、Roslyn コンパイラによって生成されたコードを検証した後、次のことがわかります。

public bool? c1(T obj)
{
    return obj != null ? new bool?(obj.Equals(null)) : null;
}

2.) c2()ケース:

私が期待したのは、c1(T) と同じコードでした。しかし、私が見ているのは次のとおりです。

public unsafe bool? c2()
{
    T* arg_33_0 = ref this.t;
    T t = default(T);
    bool? arg_43_0;
    if (t == null)
    {
        t = this.t;
        arg_33_0 = ref t;
        if (t == null)
        {
            arg_43_0 = null;
            return arg_43_0;
        }
    }
    arg_43_0 = new bool?(arg_33_0.Equals(null));
    return arg_43_0;
}

うわー、なぜこのすべての不要なコードが発行されるのですか? リリース コンパイル モードでは、C1 メソッドのコード サイズが 39 バイトであるのに対し、C2 メソッドのコード サイズは 68 バイトであることがわかります。これは最適化できるものですか?

4

1 に答える 1

4

この場合c1、CIL コードは正しくありませんc2

c1バージョンでは、Equalsのコピーで呼び出されますobj。バージョンでは、 のコピーではなく、を呼び出すように特にc2注意する必要があります。これは、独自のインスタンス データを変更するためにオーバーライドされた値型である可能性があるためです。を呼び出しているため、変更は に表示されるはずです。EqualsttTEqualsEqualstt

メソッドが返された後に誰も検査する方法がないという理由c1 だけで最適化が可能です。objobjobj

于 2016-06-12T21:40:43.653 に答える