Null 合体演算子 IList、Array、Enumerable.Empty in foreach 質問する

Null 合体演算子 IList、Array、Enumerable.Empty in foreach 質問する

この質問次のことがわかりました:

int[] array = null;

foreach (int i in array ?? Enumerable.Empty<int>())  
{  
    System.Console.WriteLine(string.Format("{0}", i));  
}  

そして

int[] returnArray = Do.Something() ?? new int[] {};

そして

... ?? new int[0]

私は次のようにNotifyCollectionChangedEventHandler適用したいと考えましたEnumerable.Empty:

foreach (DrawingPoint drawingPoint in e.OldItems ?? Enumerable.Empty<DrawingPoint>())
    this.RemovePointMarker(drawingPoint);

注記: OldItems タイプは IList

そしてそれは私に次のことを与えます:

演算子 '??' は 'System.Collections.IList' 型のオペランドには適用できません。System.Collections.Generic.IEnumerable<DrawingPoint>

しかし

foreach (DrawingPoint drawingPoint in e.OldItems ?? new int[0])

そして

foreach (DrawingPoint drawingPoint in e.OldItems ?? new int[] {})

問題なく動作します。

それはなぜですか?機能するのに機能しないのは
なぜですか?IList ?? T[]IList ?? IEnumerable<T>

ベストアンサー1

この表現を使用する場合:

a ?? b

次に、bは と同じ型であるかa、その型に暗黙的にキャスト可能である必要があります。これは、参照の場合、 の型が何であれ、 を実装または継承する必要があることを意味しますa

これらは機能します:

SomethingThatIsIListOfT ?? new T[0]
SomethingThatIsIListOfT ?? new T[] { }

なぜならT[] IList<T>配列型はそのインターフェースを実装します。

ただし、これは機能しません。

SomethingThatIsIListOfT ?? SomethingThatImplementsIEnumerableOfT

式の型は 型になりa、コンパイラはSomethingThatImplementsIEnumerableOfTも を実装することを明らかに保証できないためですIList<T>

互換性のある型になるように、2 つの側のいずれかをキャストする必要があります。

(IEnumerable<T>)SomethingThatIsIListOfT ?? SomethingThatImplementsIEnumerableOfT

これで式の型が決まりIEnumerable<T>??演算子が機能するようになりました。


「式の型は の型になりますa」は少し簡略化されており、仕様の全文は次のとおりです。


式の型は、a ?? bオペランドでどの暗黙的な変換が使用できるかによって異なります。優先順位では、 の型はa ?? bA0Aまたは ですB。ここでA、 は の型 ( がa型を持つ場合)、Bは の型b( がb型を持つ場合)、 がnull 許容型である場合はA0の基になる型、それ以外の場合は です。具体的には、は次のように処理されます。AAAa ?? b

  • が存在し、null 許容型または参照型でない場合はA、コンパイル時エラーが発生します。
  • bが動的式の場合、結果の型は動的です。実行時に、aが最初に評価されます。aが でない場合nullaは動的型に変換され、これが結果になります。 それ以外の場合はbが評価され、結果が結果になります。
  • それ以外の場合、Aが存在し、 が null 許容型であり、 から への暗黙的な変換が存在するb場合A0、結果の型は ですA0。実行時には、aが最初に評価されます。 がaでない場合null、は 型 にアンラップaされ、それが結果にA0なります。それ以外の場合はbが評価され、 型 に変換されA0、それが結果になります。
  • それ以外の場合、が存在し、からAへの暗黙的な変換が存在する場合、結果の型は です。実行時には、が最初に評価されます。が null でない場合、が結果になります。それ以外の場合はが評価され、 型 に変換されて、それが結果になります。bAAaaabA
  • それ以外の場合、 がb型を持ち、からBへの暗黙的な変換が存在する場合、結果の型は です。実行時には、が最初に評価されます。が でない場合、は 型(存在し、null 可能である場合)にアンラップされ、 型 に変換されて、結果になります。それ以外の場合はが評価され、結果になります。aBBaanullaA0ABb
  • それ以外の場合、aと はb互換性がないため、コンパイル時エラーが発生します。

おすすめ記事