有一个有趣的怪事 - 认为有人可能会提供帮助。
这是来自这个问题的可空类型的一些乐趣:
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/