Hei*_*nzi 6 c# linq ienumerable
IEnumerable不保证枚举两次会产生相同的结果.实际上,创建一个myEnumerable.First()在执行两次时返回不同值的示例非常容易:
class A {
public A(string value) { Value = value; }
public string Value {get; set; }
}
static IEnumerable<A> getFixedIEnumerable() {
return new A[] { new A("Hello"), new A("World") };
}
static IEnumerable<A> getDynamicIEnumerable() {
yield return new A("Hello");
yield return new A("World");
}
static void Main(string[] args)
{
IEnumerable<A> fix = getFixedIEnumerable();
IEnumerable<A> dyn = getDynamicIEnumerable();
Console.WriteLine(fix.First() == fix.First()); // true
Console.WriteLine(dyn.First() == dyn.First()); // false
}
Run Code Online (Sandbox Code Playgroud)
这不仅仅是一个学术性的例子:使用流行from ... in ... select new A(...) 将创造这种情况.这可能会导致意外行为:
fix.First().Value = "NEW";
Console.WriteLine(fix.First().Value); // prints NEW
dyn.First().Value = "NEW";
Console.WriteLine(dyn.First().Value); // prints Hello
Run Code Online (Sandbox Code Playgroud)
我理解为什么会这样.我也知道这可以通过ToList()在Enumerable上执行或通过覆盖==类来修复A.那不是我的问题.
问题是:当你编写一个采用任意IEnumerable的方法并且你想要一次只评估序列的属性(然后引用是"固定的")时,这样做的规范方法是什么?ToList()似乎主要使用,但如果源已经修复(例如,如果源是一个数组),引用将被复制到一个列表(不必要的,因为我需要的只是固定属性).是否有更合适的东西或者是ToList()针对这个问题的"规范"解决方案?
ToList绝对是正确的选择。
它有一些优化:如果输入枚举是一个ICollection(例如数组或列表),它将调用ICollection.CopyTo将集合复制到数组而不是实际枚举 - 因此成本不太可能很大,除非集合很大。
ICollection<T>恕我直言,一般来说,大多数方法返回orIList<T>比返回更好IEnumerable<T>,除非您想向方法的使用者暗示该实现可能使用惰性求值(例如,yield)。
如果方法应返回不可变列表,请返回只读包装器 ( ReadOnlyCollection<T>),例如通过调用ToList().AsReadOnly(),但仍返回接口类型IList<T>。
如果您遵循此准则,该方法的使用者将永远不需要对ToList.
| 归档时间: |
|
| 查看次数: |
287 次 |
| 最近记录: |