List<NewsItem>
- 我需要按日期降序对该列表进行排序,所以我编写了以下代码:newsItems.OrderByDescending(o => o.Date);
这会影响newsItems列表还是仅仅返回IOrderedEnumerable结果?
换句话说,上面的代码实际上应该这样写:
newsItems = newsItems.OrderByDescending(o => o.Date).ToList();
??
Thanks,
Dan
List<NewsItem>
- 我需要按日期降序对该列表进行排序,所以我编写了以下代码:newsItems.OrderByDescending(o => o.Date);
这会影响newsItems列表还是仅仅返回IOrderedEnumerable结果?
换句话说,上面的代码实际上应该这样写:
newsItems = newsItems.OrderByDescending(o => o.Date).ToList();
??
Thanks,
Dan
OrderByDescending
是一个扩展方法,适用于IEnumerable<T>
,该接口本身提供了只读访问。当然,这个扩展方法可能会进行转换到List<T>
,但基本上LINQ to Objects扩展方法不会影响它们的目标对象(假设目标对象不受迭代的影响,当然)。
LINQ是按照函数式风格设计的 - 方法返回数据的新视图,而不是改变调用它们的目标对象。
编辑:如drew所述,可以使用[Pure]
属性作为指示,一些工具会注意到它。然而:
[Pure]
属性[Pure]
属性(例如,在我链接的文档中看不到它)IEnumerable<T>
实例,提供代表操作结果的值序列。this
)的扩展方法。PureAttribute
属性可用于没有副作用的方法。如果您在IDE中使用ReSharper等工具,则当您尝试调用纯方法并且不使用结果时,它将警告您。因为这样的方法是纯的,在内存中没有其他可见的副作用,因此忽略结果有点愚蠢。Linq运算符带有此属性。例如,object.ToString()
。您还可以在自己的代码中使用此属性。通常通过参数(值类型或引用类型)和返回类型来确定。
如果您有一个方法签名,例如DateTime DateTime.AddDays(int days)
,则会得到两个提示:该方法不会影响原始日期时间 - 首先DateTime是值类型,其次它返回一个DateTime。如果在方法体中修改值类型,则只会将更改应用于堆栈上的副本。除非返回值类型,否则调用者永远无法观察这些更改。相比之下,引用类型可以在调用方法中进行修改,并且调用者可以观察到修改。
同样,如果您有一个方法,例如IOrderedEnumerable<T> OrderBy(IEnumerable<T> enumerable)
,尽管输入类型是引用类型(可以被修改),但提示是返回新类型,原始类型将保持不变。
最后,可以通过测试来确认这一点。作为一个有趣的一般性观点,LINQ方法链扩展方法都返回一个新的IEnumerable<T>
,是惰性评估的,并且不修改传入的IEnumerable<T>
内容,而是应用一个过滤器,该过滤器在调用返回的IEnumerable<T>
上的GetEnumerator
时进行评估。