不能将Enumerable.Count与List一起使用,编译器假定为List.Count

我还没有注意到这种行为,可能是因为我更喜欢VB.NET中的查询语法,并将查询和执行方法分成不同的语句。

如果我尝试编译以下简单查询:

Dim wordList As List(Of String) = New List(Of String) Dim longWords As Int32 = wordList.Count(Function(word) word.Length > 100) 

编译器不喜欢这样,因为他希望List.Count没有参数:

“Public Readonly Property Count As Integer”没有参数,其返回类型无法编入索引。

如果我将它声明为IEnumerable(Of String)它按预期工作:

 Dim wordSeq As IEnumerable(Of String) = New List(Of String) Dim longWords As Int32 = wordSeq.Count(Function(word) word.Length > 100) 

为什么会这样? 什么阻止编译器使用Enumerable扩展方法Count而不是ICollection.Count属性。 请注意,我添加了Imports System.LinqOption StrictOption InferOn 。 我正在使用.NET 4.0(Visual Studio 2010)。

我很困惑因为在C#中这没有问题:

 List wordList = new List(); int longWordCount = wordList.Count(word => word.Length > 100); 

这是设计 ,引自MSDN :

具有属性的情况更简单:如果扩展方法与其扩展的类的属性具有相同的名称,则扩展方法不可见且无法访问。

在C#中,只有调用属性的方法是使用属性语法(即) instance.PropertyName ,因为在Vb.Net中有两个选项。

 Dim list As List(Of String) = New List(Of String)() Dim count = list.Count() //Method 1 Dim count2 = list.Count //Method 2 

假设你添加一个没有参数的Count扩展方法, list.Count()是什么意思? 它始终优先考虑实例成员,因此它指向Property。

好的, list.Count(Function(s) s.StartsWith("a"))是什么意思? 在这种情况下,它意味着扩展方法?

那时语言没有一致性,我想设计师故意避免这个function的一致性。

如果你需要扩展方法时转换为IEnumerable,一切都会好的:

 Dim longWords As Int32 = CType(wordList, IEnumerable(Of String)).Count(Function(word) word.Length > 100) 

或者作为评论中提到的dcastro:

 Dim longWords As Int32 = wordList.AsEnumerable.Count(Function(word) word.Length > 100) 

AsEnumerable方法的主要目的之一是在IEnumerable对象的类型具有优先于LINQ扩展方法之一的成员时使用,因此您应该在调用Count之前添加对AsEnumerable调用,删除成员冲突。