.net - VB.NET 编译器如何选择要运行的扩展重载?

标签 .net vb.net extension-methods overloading

有一个有趣的怪事 - 认为有人可能会提供帮助。

这是来自这个问题的可空类型的一些乐趣:

How to check if an object is nullable?

Option Strict On

Module Test
  ' Call this overload 1
  <Extension()>
  Function IsNullable(obj As ValueType) As Boolean
    Return False
  End Function

  ' Call this overload 2
  <Extension()>
  Function IsNullable(Of T As {Structure})(obj As Nullable(Of T)) As Boolean
    Return True
  End Function

  Sub Test() 
    ' a is an integer!
    Dim a As Integer = 123

    ' calling IsNullable as an extension method calls overload 1 and returns false
    Dim result1 As Boolean = a.IsNullable()

    ' calling IsNullable as method calls overload 2 and returns true
    Dim result2 As Boolean = IsNullable(a)

    ' why? surely the compiler should treat both those calls as equivalent
  End Sub
End Module

我希望编译器会以相同的方式处理对 IsNullable 的两次调用,但事实并非如此。即使参数“a”未更改,扩展方法调用使用与普通方法调用不同的重载。

我的问题是为什么?是什么让编译器在两次调用之间改变主意?

FTR:我们使用的是 Visual Studio 2010、.NET Framework 4。

最佳答案

重载 2 将仅用作显式定义的 Nullable(of T) 的扩展。例如:

    Dim y As New Nullable(Of Integer)
    y.IsNullable()

这是因为扩展方法扩展了类型(或基类型),在这种情况下是 Nullable(of T)。调用 a.IsNullable() 永远不会调用重载 2。这是很容易弄清楚的部分。这意味着真正的问题是为什么要调用重载 2 而不是重载 1 作为标准的重载方法调用。

CLR 将通过执行“Better Conversion”检查来确定要使用哪个重载,它隐式地将传入的值转换为重载方法中定义的参数类型,然后查看规则来确定最佳使用方法。

来自 MSDN Better Conversion 文章:

If S is T1, C1 is the better conversion.

If S is T2, C2 is the better conversion.



将此代码放入 Visual Studio 将显示 Overload 2 是更好的转换,因为整数 a (S) 是 a (T2) 的隐式转换 Nullable(of Integer) 版本。
    ' a is an integer! 
    Dim a As Integer = 123

    Dim objValueType As ValueType = 123 'Or CType(a, ValueType)
    Dim objNullable As Nullable(Of Integer) = 123 'Or CType(a, Nullable(Of Integer))

    'Oh No, a compiler error for implicit conversion done for overload 1!
    Dim bolValueTypeConversionIsBetter As Boolean = (objValueType = a)

    'No error as long as Option Strict is off and it will equal True.
    Dim bolNullableConversionIsBetter As Boolean = (objNullable = a)

关于.net - VB.NET 编译器如何选择要运行的扩展重载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12319591/

相关文章:

.net - Entity Framework 中使用代码优先的 TVF(表值函数)

c# - www.asp.net/learn 不见了,还是存档在某个地方?

vb.net - 为什么在 VB.NET 中没有出现 Binding Combobox usingdictionary with the MS ACCESS database with dapper

c# - 扩展方法优先级

c# - Linq扩展方法

.net - 如何在布局 View 中使用 dbcontext(在 .NET MVC、 Entity Framework 中)

.net - 在 Linq To SQL 中更新的最佳方式

c# - 调试代码安全 .net 框架以使用 caspol.exe

xml - 如何使用 VB .net 解析 XML

dart - 我可以在 Dart 中的任何类上使用扩展方法吗?