如何VB.NET编译器选择运行扩展超载?编译器、VB、NET

2023-09-03 03:29:15 作者:薄荷味的猫

得到了一个有趣的古怪 - 以为有人也许能帮助

Got an interesting oddity - thought someone might be able to help.

这冒出来的可空类型,从这个问题的一些有趣的:

This came out of some fun with nullable types from this question:

如何检查对象是否为空的?

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是不变的。

I would expect that both calls to IsNullable would be treated the same by the compiler, but that is not the case. The extension method call uses a different overload to the normal method call even though the argument "a" is unchanged.

我的问题是为什么呢?是什么让编译器改变两个电话之间主意?

My question is why? What makes the compiler change its mind between the two calls?

FTR:我们正在使用Visual Studio 2010,.NET Framework 4的

FTR: We are using Visual Studio 2010, .NET Framework 4.

推荐答案

我的认为的这是一个错误,或者至少是VB.NET的功能。 (我只是不知道VB.NET或C的#这是错误的。)

I think this is a bug, or at least a VB.NET "feature". (I'm just not sure which of VB.NET or C# is wrong.)

我曾在LINQPad 4(因为这是我已经得到了我使用的计算机上)和C#我得到了这两个结果,为每一位值类型的课程和枚举除可空类型。

I have tried in LINQPad 4 (because that's what I've got on the machine I'm using) and for C# I got False for both results, for every value type and enum except for Nullable types, of course.

而对于VB.NET我得到的为所有的值类型和枚举,除了可空类型和值类型 [枚举] 这回,因为你不能有一个值类型? [枚举] 。随着选项严格关对象导致后期绑定,并在运行时失败找到任何超载,但第二个结果是也因为你不能有对象?

Whereas for VB.NET I get the False and True for all value types and enums, except for Nullable types, and ValueType and [Enum] which return False, False because you can't have a ValueType? or [Enum]?. With Option Strict Off, Object causes late binding, and fails at runtime to locate either overload, but the second result is False also because you can't have Object?.

有关完整性,可空类型的返回对于这两种语言的预期。

For completeness, Nullable types return True, True for both languages as expected.

这是C#是做一些不同的东西(假设我的测试是正确的),这证明了参考C#更好的转换检查是错误的(或者被误读,至少 - 在C#中是没有做什么是跨preTED为VB.NET为什么做它在做什么)。

The fact that C# is doing something different (assuming my test is correct) confirms the reference to the C# "Better Conversion" check is wrong (or being misread at least - in that C# is not doing what is being interpreted as why VB.NET is doing what it is doing).

不过,我不同意,该问题可能与隐式转换为可空(对T)现有的和莫名其妙地被一个更高优先级的隐式转换为值类型

However, I do agree that the issue is probably related to the implicit conversion to Nullable(Of T) existing and somehow being a higher priority to the implicit conversion to ValueType.

下面是我的LINQPad 4查询(C#编程):

Here's my LINQPad 4 "Query" (C# Program):

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");
    }
}