如何指定Enumerable.Count()而不是List.Count?

Dan*_*n J 9 vb.net extension-methods

尝试从Visual Basic 使用Enumerable.Count()扩展方法时,以下代码导致编译时错误:

Imports System.Linq

Module Module1

    Sub Main()
        Dim l As New List(Of Foo) From {New Foo("a"), New Foo("b"), New Foo("a")}

        Dim i As Integer = l.Count(Function(foo) foo.Bar = "a")

        Console.WriteLine(i)
        Console.ReadLine()
    End Sub

    Class Foo

        Sub New(ByVal bar As String)
            Me.Bar = bar
        End Sub

        Public Property Bar As String
    End Class
End Module
Run Code Online (Sandbox Code Playgroud)

产生的错误是:

'Public ReadOnly Property Count As Integer'没有参数,其返回类型无法编入索引.

我的目标是.NET 4.0,因此应该支持扩展方法.值得注意的是,C#中的等效代码正确地推断了扩展方法......

为什么编译器无法推断出使用Enumerable.Count的,因为我是作为参数传递的谓词,以及如何能我使用扩展方法,而不是名单的Count属性?

slo*_*oth 7

该VB.Net编译器首先尝试查找Count的List实例,它找到的Count财产.由于字段和属性始终按名称影子扩展方法,因此使用此属性代替扩展方法.我不知道在Visual Basic语言规范中说明了哪些内容,但您可以在此MSDN杂志文章中阅读更多内容:

字段和属性始终按名称影子扩展方法.图4显示了具有相同名称和各种调用的扩展方法和公共字段.虽然扩展方法包含了第二个参数,字段阴影的名字,并使用该名称结果访问该领域的所有呼叫的扩展方法.各种重载调用将所有编译,但在运行时,其结果可能是出乎意料的,因为他们会绑定到属性,并使用默认属性的行为,以返回单个字符或导致运行时异常.选择扩展方法的名称非常重要,这样可以避免与属性,字段和现有实例方法发生冲突.

因此,Count(Function(foo) foo.Bar = "a")可能意味着:调用Count-property Function(foo) foo.Bar = "a",或者获取-property 的结果Count并将其索引Function(foo) foo.Bar = "a",这可能是完全有效的,因为VB.Net中的索引属性可以采用任何参数.

这适用于C#(我猜),因为C#编译器更容易区分方法调用和属性访问,因为与VB.Net不同,C#不允许在属性和索引属性上使用任意参数.


要使用扩展方法,您可以像调用其他所有静态(共享)方法一样调用它:

Dim i As Integer = Enumerable.Count(l, Function(foo) foo.Bar = "a")
Run Code Online (Sandbox Code Playgroud)

或致电Call上IEnumerable明确:

Dim i As Integer = l.AsEnumerable().Count(Function(foo) foo.Bar = "a")
Run Code Online (Sandbox Code Playgroud)


Mar*_*ark 2

回答你的问题,为什么VB不能做 C# 在这种情况下可以做的事情......

VB 允许您访问()名称后带有 的属性,还允许您通过省略(). 此外,索引器使用圆括号,而不是 C# 中的方括号。这些是 VB 的巨大功能的示例,这些功能旨在使编程变得更容易,但实际上会导致代码更加模糊、难以理解且容易出现错误。

因此,在这种特殊情况下,VB 看到您正在访问 Count,并假定其后面的括号是 Count 属性的索引器,而不是 Count 函数的参数。

C# 看到圆括号,并意识到您没有访问索引器,您必须调用一个函数,因此会查找一个函数。

当然,C# 中也存在歧义的地方。例如,与扩展方法同名的属性将优先于扩展方法被调用,该属性返回委托类型...

public Action Count { get; set; }
Run Code Online (Sandbox Code Playgroud)

啊……幸福的日子。

至于如何调用 IEnumerable.Count() 函数,强制转换(最好DirectCast())或直接执行扩展方法Enumerable.Count(...),比创建一个全新的数组来调用 count 要好得多......!