9

谁能告诉我VB中的aFunc和a有什么区别。Function

例如,请参阅以下内容:

Dim F As Func(Of String) = Function() As String
                             Return "B"
                           End Function
Dim F2 = Function() As String
           Return "B"
         End Function
  • F显示为Func(Of String)
  • F2作为一个Function() As String.

看起来他们做同样的事情,但考虑到编译器认为他们有不同的类型,肯定有微妙之处。

此致

查尔斯

4

3 回答 3

4

F 显示为 Func(Of String) F2 显示为 Function() 作为字符串。

不,它没有。在这两种情况下,变量类型都是等效于Func(Of String). 再仔细看一下代码——两个声明都有两个部分;声明本身:

Dim F As Func(Of String)
' and
Dim F2

…以及初始化:

Function() As String
    Return "B"
End Function

' and

Function() As String
    Return "B"
End Function

如您所见,初始化是相同的。只是声明不同,因为我们在第二种情况下省略了显式变量类型。感谢Option Infer,编译器可以为我们推断它。

事实上,VB 语言规范有这样的说法(第 8.4.2 节):

当分类为 lambda 方法的表达式在没有目标类型(例如Dim x = Function(a As Integer, b As Integer) a + b)的上下文中被重新分类为值时,生成的表达式的类型是等效于 lambda 方法签名的匿名委托类型。[强调我的]

最后,那么Func和之间有什么区别Function

Function是一个引入函数的关键字——可以是代码中的匿名函数 (lambda),也可以是具有名称的“普通”函数,如以下代码:

Function F() As String
    Return "B"
End Function

Func(Of T…)另一方面是委托的泛型类型。lambda 或委托可以绑定到使用合适Func类型声明的变量。这发生在您的代码中。

于 2013-07-04T11:53:29.257 回答
4

Func(Of TResult)()是一个名为 的特定委托Func。它是在System命名空间内声明的类型,如下所示:

Public Delegate Function Func(Of TResult)() As TResult

它可能有不同的命名。例如:

Public Delegate Function MyParameterLessFunction(Of TResult)() As TResult

所以Func实际上只是给代表的名字。由于F2没有明确指定的类型,VB 不知道这个委托的名称。是它Func还是MyParameterLessFunction别的什么?相反,VB 只显示它的签名Function() As String,因为F2它也适合声明为的非泛型委托

Public Delegate Function AnonymousParameterLessStringFunction() As String

在您的评论中,您使用.ToString()onFF2。这将返回运行时类型,即分配给这些变量的值的类型。这些类型可以不同于这些变量的静态类型,即赋予变量名称的类型。让我们做一个小测试

Imports System.Reflection

Module FuncVsFunction
    Dim F As Func(Of String) = Function() As String
                                   Return "B"
                               End Function
    Dim F2 = Function() As String
                 Return "B"
             End Function

    Sub Test()
        Console.WriteLine($"Run-time type of F:  {F.ToString()}")
        Console.WriteLine($"Run-time type of F2: {F2.ToString()}")

        Dim moduleType = GetType(FuncVsFunction)
        Dim fields As IEnumerable(Of FieldInfo) = moduleType _
            .GetMembers(BindingFlags.NonPublic Or BindingFlags.Static) _
            .OfType(Of FieldInfo)

        For Each member In fields
            Console.WriteLine($"Static type of {member.Name}: {member.FieldType.Name}")
        Next
        Console.ReadKey()
    End Sub
End Module

它显示

Run-time type of F:  System.Func`1[System.String]
Run-time type of F2: VB$AnonymousDelegate_0`1[System.String]
Static type of F: System.Func`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
Static type of F2: System.Object

请注意,F2它只是简单地键入为Object. 这是一个惊喜。我希望它是一个委托类型。


您还可以在调试器中看到这种差异。如果您在方法中设置断点Test,然后将鼠标悬停在 and 的关键字Dim上,则会显示一个弹出窗口FF2

'Dim of F (static type)
Delegate Function System.Func(Of Out TResult)() As String

'Dim of F2 (static type)
Class System.Object

如果将鼠标悬停在变量名称上

'F (run-time type)
Method = {System.String _Lambda$__0-0()}

'F2 (run-time type)
<generated method>

因为F您不仅可以获得类型信息,还可以获得生成的方法本身的名称。由于F2是一个对象,Visual Studio 显然没有像F.

于 2013-07-04T12:50:22.280 回答
0

Func是委托类型 - System.Func

Function是用于创建 lambda 表达式的关键字。

上面的 lambda 表达式是System.Linq.Expression(Of System.Func(Of String))类型,并且确实可以隐式转换为委托类型Func(Of String)

不同之处在于表达式存储为表达式树 - 描述了代码的结构。在隐式转换期间,它实际上被编译为委托。

于 2013-07-04T11:59:21.987 回答