类型<T> 作为回报类型
-
22-08-2019 - |
题
是有一个问题与使用 IEnumerable<T>
作为返回的类型?FxCop抱怨回来 List<T>
(它建议返回 Collection<T>
相反).
嗯,我一直指导规则"接受至少你可以,但是回报最大。"
从这一点来看,回返的 IEnumerable<T>
是一件坏事,但我应该怎么做的时候,我希望使用"懒惰的检索"?还有, yield
关键词是这样的礼.
解决方案
这是一个真正的问题的两个部分。
1)是否有固有什么毛病返回一个IEnumerable
没有什么都没有。事实上,如果你使用的是C#迭代这是预期的行为。将其转换为一个List
2)是否有其中可以优选以返回比IEnumerable的其他东西的任何情况
是。虽然它不是一个伟大的想法,认为很多关于您的呼叫,这是完全没关系根据自己的行为做出决定。想象一下,你有一个多线程的物体在请求排队到这是不断更新的对象的场景。在这种情况下返回原始的IEnumerable
这肯定是较少见的情况虽然。
其他提示
没有,IEnumerable<T>
是的好的事情回到这里,因为你是有希望的是“(类型)值序列”。非常适于LINQ等,并完全可用。
调用者可以很容易地把这个数据到一个列表(或其他) - 特别是与LINQ(ToList
,ToArray
等)
这个方法允许您懒惰地卷轴回值,而不是具有缓冲的所有数据。这绝对是一个礼包。我写行动另一个有用的IEnumerable<T>
招前些天得。
关于你的原则:“接受你至少可以,但返回的最大”
于管理一个大程序的复杂性的关键是一个名为技术信息隐藏。如果你的方法通过构建List<T>
de,这不是经常需要通过返回类型来揭示这一事实。如果这样做,那么你的来电者可以修改他们回到列表。这将删除你做的缓存能力,或慵懒迭代与yield return
。
因此,一个更好的原则是按照功能是:“揭示尽可能少你是如何工作的”
IEnumerable的是我不错,但它也有一些缺点。客户端具有枚举得到的结果。它有没有办法来检查计数等。 因为你暴露过多的控制列表是坏的;客户可以从中添加/删除等,并且可以是一件坏事。 集合似乎是最好的compromomise,至少在的FxCop的观点。 我用百达在什么情况下我似乎appropiate(例如,如果我想返回一个只读集合我揭露集合作为返回类型,并通过产量等返回List.AsReadOnly()或IEnumerable的懒惰的评价)。把它在逐案
"接受至少你可以,但是返回的最大"是什么我的倡导者。当一个方法回报的对象,有什么理由,我们必须不返回的实际类型和限制能力的对象,通过返回的一个基本类型。然而,这就提出了一个问题我们怎么知道的"最大"(实际类型)将当我们设计一个接口。答案是很简单的。只有在极端的情况下接口的设计师设计一个开放的接口,这将实现的外部应用程序/分,他们不会知道什么样的实际回报类型的可能。一个智能设计师应始终考虑有什么方法应该做什么的一个最优/泛返回的类型应该的。
E.g。如果我设计的一个接口检索一矢量的目的,我知道计数的返回对象是会变的,我会总是假定的智能的开发将始终使用一个清单。如果有人计划返回的一个阵列,我怀疑他的能力,除非他/她只是返回的数据从另一个层,他/她不自己。这可能是为什么FxCop倡导ICollection(共同基础表和阵列)。
上面所说,有几个其他的事情要考虑
如果返回的数据应该是可变的或不可改变的
如果返回的数据共享跨多个呼叫
关于皇宫偷懒的评估,我确信95%+C#用户不了解intestacies.它是如此的非oo-ish。OO促进具体的国家改变方法调用。皇宫偷懒评价促进运行状态变化的表达的评估模式(不是的东西不高级用户总是按照).
返回的IEnumerable
但正如其他人指出,它的缺点是主叫方可能需要枚举,如果他需要的任何其他信息(例如计数)。的.NET 3.5扩展方法IEnumerable
我经常回的IList
一个重要方面是,当你返回List<T>
你是实际返回的参考即可。这使得它可能呼叫者操纵你的列表中。这是一个常见的问题,例如,一个返回List<T>
到GUI层业务层。
就因为你说你回来了IEnumerable并不意味着你不能返回一个列表。这样做是为了减少不必要的耦合。所有调用者应该关心的是越来越的事情的清单,而不是用于包含列表收集的确切类型。如果你有东西是由数组支持,然后让像计数将是快速反正。
我觉得自己的指导,是伟大的 - 如果你能具体谈谈你回到什么没有性能损失(你不必例如建立一个列表,你的结果),这样做。但是,如果你的函数合法不知道它会发现,就像如果在某些情况下,你会用一个列表,并在一些与阵列工作等,然后返回IEnumerable的是“最好的”你可以做什么类型。把它看成是“最伟大的公倍数”一切你可能要回来。
我无法接受的选择答案。有与所描述的场景中处理,但使用列表或其他任何您的使用是不是其中的一个方式。当下的IEnumerable返回你必须假设主叫方可能会做一个foreach。在这种情况下,如果具体类型的列表或意大利面也没关系。实际上只是索引是,特别是如果被除去的物品中的问题。
任何返回值是一个快照。这可能是在这种情况下,如果它的缓存也应该是缓存副本的克隆了IEnumerable的当前内容;如果它应该是更加动态(如SQL查询的resuts),然后使用收益率的回报;然而,允许容器随意变异,并提供像计数和索引方法是在多线程世界带来灾难性的后果。我还没有得到到调用方打电话给你的代码应该是在控制的容器中添加或删除的能力。
此外返回一个具体类型的锁你进入一个实现。今天,在内部你可能会使用列表。明天也许你并成为多线程,并且希望使用一个线程安全的容器或数组或队列或字典的值集合或LINQ查询的输出。如果你把自己锁进一个具体的返回类型,那么你必须要么改变一串代码或返回之前做了转换。