Jam*_*ose 7 .net vb.net extension-methods overloading
有一个有趣的奇怪 - 认为有人可能会帮助.
这可以从这个问题的可空类型中获得一些乐趣:
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
Run Code Online (Sandbox Code Playgroud)
我希望编译器对IsNullable的两次调用都是一样的,但事实并非如此.即使参数"a"未更改,扩展方法调用也会对普通方法调用使用不同的重载.
我的问题是为什么?是什么让编译器在两次调用之间改变主意?
FTR:我们使用的是Visual Studio 2010,.NET Framework 4.
我认为这是一个错误,或者至少是 VB.NET“功能”。(我只是不确定 VB.NET 或 C# 哪个是错误的。)
我已经在 LINQPad 4 中进行了尝试(因为这就是我正在使用的机器上得到的),对于 C#,我得到了两个结果,当然,False除了类型之外的每个值类型和枚举。Nullable
而对于 VB.NET,我得到了所有值类型和枚举的Falseand True,除了Nullable类型, and ValueType,[Enum]它返回False,False因为你不能有ValueType?or [Enum]?。使用Option Strict Off,Object会导致后期绑定,并且在运行时无法找到任一重载,但第二个结果也是False因为您无法拥有Object?.
为了完整起见,按预期为两种语言Nullable键入 return True, 。True
事实上,C# 正在做一些不同的事情(假设我的测试是正确的),这证实了对 C#“更好转换”检查的引用是错误的(或者至少被误读了 - 因为 C# 没有做被解释为 VB.NET 的原因)正在做它正在做的事情)。
但是,我确实同意该问题可能与隐式转换为Nullable(Of T)现有的并且以某种方式比隐式转换为更高的优先级有关ValueType。
这是我的 LINQPad 4“查询”(C# 程序):
void Main()
{
Test.test();
}
// Define other methods and classes here
static class Test
{
static bool IsNullable(this ValueType obj)
{
return false;
}
static bool IsNullable<T>(this T? obj) where T:struct
{
return true;
}
public static void test()
{
int x = 42;
bool result1 = x.IsNullable();
bool result2 = IsNullable(x);
result1.Dump("result1");
result2.Dump("result2");
}
}
Run Code Online (Sandbox Code Playgroud)