Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/symfony/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Interface C#IEnumerable、ICollection、IList还是List?_Interface_Ienumerable - Fatal编程技术网

Interface C#IEnumerable、ICollection、IList还是List?

Interface C#IEnumerable、ICollection、IList还是List?,interface,ienumerable,Interface,Ienumerable,有人能解释一下为什么我们总是在C语言中使用IEnumerable,而根据我的逻辑,我们应该使用List、IList或ICollection 看看这个提交修复程序。 好的,1)IEnumarable应该只用于只读集合 太好了,每个人都在重复(我明白了),那么为什么我需要不断地在每个数据库调用上放置ToList(),以防止原始线程处理上下文时多线程崩溃呢 当然,一旦查询被枚举到一个列表中,我们就应该从那里开始使用List,以避免混淆、线程安全问题以及不断地在每个模型上调用ToList() 同样在解

有人能解释一下为什么我们总是在C语言中使用
IEnumerable
,而根据我的逻辑,我们应该使用
List
IList
ICollection

看看这个提交修复程序。

好的,1)IEnumarable应该只用于只读集合

太好了,每个人都在重复(我明白了),那么为什么我需要不断地在每个数据库调用上放置
ToList()
,以防止原始线程处理上下文时多线程崩溃呢

当然,一旦查询被枚举到一个列表中,我们就应该从那里开始使用List,以避免混淆、线程安全问题以及不断地在每个模型上调用
ToList()

同样在解析JSON(一个已经枚举的对象的文本表示)的WebAPI上,我们再次将其存储为IEnumarable。我们已经知道了它的大小,我们对延迟加载不感兴趣,我们可能会在某个地方修改这个对象,所以我们为什么不将它存储为列表呢

--编辑

这个问题的一个重要方面是我从来都不知道


由于列表实现存在运行时问题,因此无法执行
List
,因此必须使用
IEnumarable
——这仅在两个不同系统上具有相同实体且需要处理一段代码的特定情况下才有意义。否则,自从我提出这个问题以来,我一直在使用
List
,这可能是在业务层中正确使用的90%。数据库/存储库层坚持使用iCollection now或IQueryable

IEnumerable没有明确说明数据集的收集类型,因此您可以进行更多的通用编程,而不是针对特定类型使用特定函数。

回答这个问题有点困难,因为很容易发表意见,而不是回答。不过我会试试的

这是一个关于责任的基本问题,更具体地说,就是好的API设计

以下是我对API设计世界中的特定角落的一些想法:

  • 在输出类型中尽可能具体
  • 在输入类型中尽可能开放
我将举几个例子。如果您的方法可以接受任何集合,请接受
IEnumerable
。如果您的方法需要一个可索引的集合,请使用
IList
或类似方法。如果该方法所做的第一件事是通过
.ToList()
将输入转换为列表,请对此保持开放态度。如果我已经在外部有一个列表,并且我想将它提供给您的方法,那么请使用
list

然而,我必须意识到一个事实,一旦你说你使用了
IList
你就可以修改列表了。如果可以的话,很好,我可以把我的清单寄给你。否则,我将不得不在外部执行
.ToList()
。这并没有比以前更糟,只是一个谁应该对此负责的问题

另一方面,如果方法返回的对象是
列表
,则将其作为
列表
IList
返回。不要将它隐藏在
IEnumerable
后面

在这里,您还应该知道,任何获取此列表的调用方都可以修改它。如果不正常,请不要将其作为
IList
返回

不过,在最后一个示例中,您可以说,如果该列表不应该在外部修改,那么在返回后(它不是调用方列表),您应该将它隐藏在
IEnumerable
后面,但这只会隐藏一个事实,程序员仍然可以将它放回
IList
并修改它。如果您不能接受,请通过
.ToList()
返回一份副本

然而,所有这些都回到了责任上来

如果您的方法返回
IEnumerable
,那么作为使用此方法编写代码的人,我是否应该依靠您的方法正常工作?如果您的方法无法工作,因为您已经处理了数据库上下文,那么这取决于您、您的代码、您的bug和您的问题

类似地,如果我需要可以编入索引的内容,但不是纯粹的只读集合,那么我应该设计我的方法,使用适当的集合接口来表示这一点。如果我将我的方法设计为采用
IEnumerable
,我应该知道我明确地说“我将采用任何延迟生成的集合”。如果我不知道,或者不想说,那么我就不应该接受
IEnumerable

以便回答特定代码行的基本问题。在这里,您绝对必须在内部调用
.ToList()
,否则您的方法将被破坏、错误、错误

,您可以重新设计方法,使其保持惰性,但在准备好之前不处理数据库上下文。在这方面,对您的方法的一个简单更改是使用
收益率回报

using (var context = ... )
{
    foreach (var element in context.Request(...))
        yield return element;
}
通过这样的更改,您仍然会推迟访问数据库的实际成本,直到调用方实际迭代您返回的集合,并且您仍然正确地处理了上下文(假设调用方的迭代正确)。在这里,我仍然会返回
IEnumerable
,明确地说“我被惰性地评估了”


但是,如果您内部生成的列表没有保留,没有人对此负责,您实际上是将此列表的责任交给了调用者,那么您绝对应该将其作为
list
返回。不要把它藏在
IEnumerable
后面。。但是,如果总是引起问题,为什么我们总是需要让一切通用化:尤其是IEnumarable的工作原理与IList完全不同。。它们并不常见,但IEnumarable是最小的接口。这有点烦人1)它会引起什么问题