Null coalescing operator IList, Array, Enumerable.Empty in foreach
在这里,我发现下面的问题:
1 2 3 4 5 6 | int[] array = null; foreach (int i in array ?? Enumerable.Empty<int>()) { System.Console.WriteLine(string.Format("{0}", i)); } |
鸭
1 |
鸭
1 |
我想在一个
1 2 | foreach (DrawingPoint drawingPoint in e.OldItems ?? Enumerable.Empty<DrawingPoint>()) this.RemovePointMarker(drawingPoint); |
注:
它给了我。
Operator '??' cannot be applied to operands of type 'System.Collections.IList' and
System.Collections.Generic.IEnumerable
然而,
1 |
鸭
1 |
工作只是罚款。
这是为什么呢? 为什么
使用此表达式时:
1 | a ?? b |
那么,
这些工作:
号
由于
但是,这不起作用:
1 | SomethingThatIsIListOfT ?? SomethingThatImplementsIEnumerableOfT |
因为表达式的类型将是
您将不得不在两个方面中的一个进行强制转换,这样您就有了兼容的类型:
1 | (IEnumerable<T>)SomethingThatIsIListOfT ?? SomethingThatImplementsIEnumerableOfT |
。
现在表达式的类型是
"表达式类型将是
表达式
- 如果
a 存在且不是可以为空的类型或引用类型,则会发生编译时错误。 - 如果
b 是动态表达式,则结果类型为动态。在运行时,首先对a 进行评估。如果a 不是null 的话,a 转换为动态类型,这就是结果。否则,评估b ,结果即为结果。 - 否则,如果
a 存在并且是可以为空的类型,并且存在从b 到A0 的隐式转换,则结果类型为A0 。在运行时,首先对a 进行评估。如果a 不是null 型,则a 被解包为A0 型,成为结果。否则,对b 进行评估,转换为A0 型,即为结果。 - 否则,如果存在
a 且存在从b 到a 的隐式转换,则结果类型为a 。在运行时,首先对a 进行评估。如果a 不为空,则结果为a 。否则,对b 进行评估,并转换为a 型,即为结果。 - 否则,如果
b 具有b 类型,并且存在从a 到b 的隐式转换,则结果类型为b 。在运行时,首先对a 进行评估。如果a 不是null ,则a 展开为A0 型(如果a 存在且可以为空),并转换为b 型,即为结果。否则,将对b 进行评估并成为结果。 - 否则,
a 和b 不兼容,出现编译时错误。
您使用非泛型
我建议你这样做:
1 2 | foreach (DrawingPoint drawingPoint in e.OldItems ?? Array.Empty<DrawingPoint>()) ... |
相反。这将起作用,因为任何
在这种情况下,由
一般来说,我会避免使用非通用的
我看到了一个由克库里(在线程中的另一个答案)发表的评论,它已经暗示了
1 2 3 4 | public static class EmptyArray<TElement> { public static readonly TElement[] Value = new TElement[] { }; } |
号
或者只是:
1 2 3 4 | public static class EmptyArray<TElement> { public static readonly TElement[] Value = { }; } |
然后:
1 2 | foreach (DrawingPoint drawingPoint in e.OldItems ?? EmptyArray<DrawingPoint>.Value) ... |
。
就像
最后一个建议是强制
1 2 3 4 | foreach (var drawingPoint in e.OldItems?.Cast<DrawingPoint> ?? Enumerable.Empty<DrawingPoint>() ) ... |
注意使用
我相信它决定了FIRS成员的结果类型,在您的情况下是IList。第一种情况起作用,因为数组实现了IList。对于IEnumerable,这不是真的。
这只是我的猜测,因为文档中没有详细信息??操作员在线。
UPD。正如它在接受的问题中指出的,在C规范(ECMA或Github)中有很多关于这个主题的详细信息。