我使用Linq来过滤从数据库中获取的数据。由于设计选择,1方法返回IEnumerable<int>
然后我将其用于linq语句以查看允许返回哪些ID(代码如下)。我的问题是因为我在文档中没有看到任何内容:Contains方法是否隐式地将IEnumerable强制转换为要执行的语句的List? (如果是这样,问题是如果首先使用List而不是IEnumerable更好)。
代码示例
private List<MyData> GetAllPermittedData()
{
IEnumerable<int> permitteddIds = GetPermittedIDs();
return (from a in MyDataHandler.GetAllData() where permittedIds.Contains(a.Id)
select a);
}
就像我上面提到的那样,我不确定Contains
部分是否隐式将allowedIds转换为List<int>
(在使用Contains语句时/内部)。如果是这种情况,那么后续问题就是如果不是更好地已经使用以下语句(性能方面):
private List<MyData> GetAllPermittedData()
{
List<int> permitteddIds = GetPermittedIDs().ToList();
return (from a in MyDataHandler.GetAllData() where permittedIds.Contains(a.Id)
select a);
}
答案 0 :(得分:3)
LINQ运算符将首先尝试将其强制转换为ICollection<T>
。如果转换成功,则使用该方法。由于List<T>
实现了这个接口,它将使用list的contains方法。
请注意,如果您使用接受IEqualityComparer
的重载,则必须遍历可枚举,并且不会执行ICollection
快捷方式。
您可以在.NET Framework reference source中看到此实现:
public static bool Contains<TSource>(this IEnumerable<TSource> source, TSource value) {
ICollection<TSource> collection = source as ICollection<TSource>;
if (collection != null) return collection.Contains(value);
return Contains<TSource>(source, value, null);
}
Jon Skeet还有一个很好(又冗长)的博客系列,名为“Reimplementing LINQ”,他深入讨论了实施。他专门涵盖了part 32 of his blog中的Contains
。
答案 1 :(得分:0)
Contains
method 可能尝试将传递的IEnumerable<T>
投放到IList<T>
或ICollection<T>
。如果演员成功,它可以直接使用IList<T>
的方法,否则它将枚举整个序列。
请注意,我正在编写 may ,因为这是特定于实现的,并且未在文档中指定。因此,它可能在.NET版本和Mono等替代实现中有所不同。
仅提供IEnumerable<T>
的优势在于,您可以更自由地交换从该属性返回的对象,而无需更改公共接口。尝试施放到IList<T>
或类似物品的性能成本应该可以忽略不计。
在任何情况下,这种方式都比您调用ToList
的建议更有效,因为它实际上会创建一个新的List<T>
并将枚举中的所有项目复制到其中。
答案 2 :(得分:-1)
Contains
作为IEnumerable<T>
的{{3}}存在。但是您不需要将IEnumerable转换为List<T>
ToList()
,您只需使用IEnumerable<T>
extension method fill:< / p>
var permitteddIds = new HashSet<int>(GetPermittedIDs());