首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >何时退还IOrderedEnumerable?

何时退还IOrderedEnumerable?
EN

Stack Overflow用户
提问于 2011-12-15 18:26:40
回答 3查看 10.3K关注 0票数 26

IOrderedEnumerable是否应该纯粹用作语义值的返回类型?

例如,当使用表示层中的模型时,我们如何知道集合是否需要排序或已经排序?

如果存储库使用ORDER BY子句包装存储过程,情况会怎样呢?存储库应该返回IOrderedEnumerable吗?那该如何实现呢?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-12-15 18:56:08

我不认为这是个好主意:

是否应该将IOrderedEnumerable纯粹用作语义值的返回类型?

例如,当使用表示层中的模型时,我们如何知道集合是否需要排序或已经排序?

如果您不知道序列是按哪个键排序的,那么知道序列是有序的又有什么意义呢?IOrderedEnumerable接口的目的是能够添加第二个排序标准,如果您不知道主要排序标准是什么,这就没有多大意义。

如果存储库使用ORDER BY子句包装存储过程,该怎么办?存储库应该返回IOrderedEnumerable吗?那该如何实现呢?

这没有任何意义。正如我已经说过的,IOrderedEnumerable用于添加辅助排序条件,但是当存储过程返回数据时,数据已经排序,添加辅助排序条件为时已晚。您所能做的就是完全重新排序,因此对结果调用ThenBy不会有预期的效果。

票数 22
EN

Stack Overflow用户

发布于 2011-12-15 20:03:33

正如Thomas所指出的,知道一个对象是一个IOrderedEnumerable只告诉我们它是以某种方式排序的,而不是以我们希望维护的方式排序的。

还值得注意的是,返回类型将影响重写和编译能力,但不会影响运行时检查:

代码语言:javascript
复制
private static IOrderedEnumerable<int> ReturnOrdered(){return new int[]{1,2,3}.OrderBy(x => x);}
private static IEnumerable<int> ReturnOrderUnknown(){return ReturnOrdered();}//same object, diff return type.
private static void UseEnumerable(IEnumerable<int> col){Console.WriteLine("Unordered");}
private static void UseEnumerable(IOrderedEnumerable<int> col){Console.WriteLine("Ordered");}
private static void ExamineEnumerable(IEnumerable<int> col)
{
  if(col is IOrderedEnumerable<int>)
    Console.WriteLine("Enumerable is ordered");
  else
    Console.WriteLine("Enumerable is unordered");
}
public static void Main(string[] args)
{
  //Demonstrate compile-time loses info from return types
  //if variable can take either:
  var orderUnknown = ReturnOrderUnknown();
  UseEnumerable(orderUnknown);//"Unordered";
  orderUnknown = ReturnOrdered();
  UseEnumerable(orderUnknown);//"Unordered"
  //Demonstate this wasn't a bug in the overload selection:
  UseEnumerable(ReturnOrdered());//"Ordered"'
  //Demonstrate run-time will see "deeper" than the return type anyway:
  ExamineEnumerable(ReturnOrderUnknown());//Enumerable is ordered.
}

因此,如果您遇到这样的情况,根据环境的不同,可能会有IEnumerable<T>IOrderedEnumerable<T>返回给调用者,变量将被类型化为IEnumerable<T>,并且返回类型的信息将丢失。同时,无论返回类型是什么,调用者都能够确定该类型是否真的是IOrderedEnumerable<T>

无论哪种方式,返回类型都无关紧要。

返回类型的权衡是调用者的实用性和被调用者的灵活性。

考虑一个当前以return currentResults.ToList()结尾的方法。以下返回类型是可能的:

  1. List<T>
  2. IList<T>
  3. ICollection<T>
  4. IEnumerable<T>
  5. IList
  6. ICollection
  7. IEnumerable
  8. object

现在让我们排除object和非泛型类型,因为它们不太可能有用(在它们可能有用的情况下,使用它们可能是不需要动脑筋的决定)。剩下的就是:

  1. List<T>
  2. IList<T>
  3. ICollection<T>
  4. IEnumerable<T>

列表越靠前,我们就越方便调用者使用该类型公开的功能,而不是下面的类型公开的功能。列表越靠后,我们给被调用者更多的灵活性来改变未来的实现。因此,理想情况下,我们希望在方法的目的上下文中尽可能靠前(向调用者公开有用的功能,并减少创建新集合以提供我们已经提供的功能的情况),而不是更高(以允许将来的更改)。

因此,回到我们的例子中,我们有一个可以作为IOrderedEnumerable<TElement>IEnumerable<T> (或IEnumerableobject)返回的IOrderedEnumerable<TElement>

问题是,这是一个与方法的目的内在相关的IOrderedEnumerable的事实,还是仅仅是一个实现的人工产物?

如果我们有一个方法ReturnProducts碰巧按价格排序,作为删除相同产品以不同价格提供两次的情况的实现的一部分,那么它应该返回IEnumerable<Product>,因为调用者不应该关心它是否被订购,当然也不应该依赖它。

如果我们有一个方法ReturnProductsOrderedByPrice,其中排序是它的目的的一部分,那么我们应该返回IOrderedEnumerable<Product>,因为这与它的目的更密切相关,并且可以合理地预期对它调用CreateOrderedEnumerableThenByThenByDescending (这是唯一真正提供的东西),并且不会因为对实现的后续更改而中断这一点。

编辑:我错过了这篇文章的第二部分。

如果存储库使用ORDER BY子句包装存储过程,该怎么办?存储库应该返回IOrderedEnumerable吗?那该如何实现呢?

在可能的情况下,这是一个相当好的想法(或者IOrderedQueryable<T>)。然而,这并不简单。

首先,您必须确保ORDER BY之后的任何操作都不能取消排序,这可能不是微不足道的。

其次,您不能在调用CreateOrderedEnumerable<TKey>()时取消这种排序。

例如,如果从使用ORDER BY A DESCENDING, B的对象返回具有字段ABCD的元素,则会返回一个名为MyOrderedEnumerable<El>的类型,该类型实现了IOrderedEnumerable<El>。然后,必须存储AB是排序的字段这一事实。对CreateOrderedEnumerable(e => e.D, Comparer<int>.Default, false)的调用(这也是ThenByThenByDescending调用的内容)必须接受多组元素,这些元素按照数据库返回的相同规则对AB进行同等比较(数据库和.NET之间的排序规则可能很难匹配),而且只有在这些组中,才必须根据cmp.Compare(e0.D, e1.D)进行排序。

如果可以这样做,这将非常有用,并且如果所有调用使用的所有查询都存在ORDER BY子句,则返回类型为IOrderedEnumerable将是完全合适的。

否则,IOrderedEnumerable将是一个谎言--因为你无法履行它提供的合同--而且它将是无用的。

票数 10
EN

Stack Overflow用户

发布于 2019-07-16 13:14:35

IMO IOrderedEnumerableIOrderedCollection对于高级操作非常有用,即处理列表和数组,而不是处理集合,但是列表不知何故没有继承它,所以它失去了这个目的。现在,它只适用于您在问题的第二部分中显示的那种思考(order by等)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8518557

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档