Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
VB.NET编译器如何选择要运行的扩展重载?_.net_Vb.net_Extension Methods_Overloading - Fatal编程技术网

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

VB.NET编译器如何选择要运行的扩展重载?,.net,vb.net,extension-methods,overloading,.net,Vb.net,Extension Methods,Overloading,有一个有趣的怪事——我想也许有人能帮上忙 这源于这个问题中的可空类型带来的一些乐趣: 选项严格打开 模块测试 '将此称为重载1 作为布尔值的函数IsNullable(obj作为ValueType) 返回错误 端函数 “称之为过载2 函数IsNullable(T的{Structure})(obj作为Nullable(T的))作为布尔值 返回真值 端函数 子测试() “a是一个整数! 将a调整为整数=123 '作为扩展方法调用IsNullable将调用重载1并返回false Dim result1

有一个有趣的怪事——我想也许有人能帮上忙

这源于这个问题中的可空类型带来的一些乐趣:

选项严格打开
模块测试
'将此称为重载1
作为布尔值的函数IsNullable(obj作为ValueType)
返回错误
端函数
“称之为过载2
函数IsNullable(T的{Structure})(obj作为Nullable(T的))作为布尔值
返回真值
端函数
子测试()
“a是一个整数!
将a调整为整数=123
'作为扩展方法调用IsNullable将调用重载1并返回false
Dim result1作为布尔值=a.IsNullable()
'调用IsNullable as方法调用重载2并返回true
Dim result2为布尔值=可为空(a)
”“为什么?当然,编译器应该将这两个调用视为等价的
端接头
端模块
我希望编译器对IsNullable的两个调用的处理是相同的,但事实并非如此。扩展方法调用使用与普通方法调用不同的重载,即使参数“a”不变

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


FTR:我们正在使用Visual Studio 2010、.NET Framework 4。

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

    Dim y As New Nullable(Of Integer)
    y.IsNullable()
这是因为扩展方法扩展了类型(或基类型),在本例中,它是可为null的(T)。调用.IsNullable()永远不会调用重载2。这是最容易理解的部分。这意味着真正的问题是,为什么要调用重载2而不是重载1作为标准重载方法调用

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

从MSDN Better Conversion文章:

如果S是T1,则C1是更好的转换

如果S是T2,则C2是更好的转换

将此代码放入Visual Studio将向您显示重载2是更好的转换,因为整数a(S)是a(T2)的隐式转换的可为null(of integer)版本

我认为这是一个bug,或者至少是一个VB.NET“特性”。(我只是不确定VB.NET或C#哪一个是错的。)

我在LINQPad 4中进行了尝试(因为这是我在使用的机器上得到的结果),对于C#,我得到了两个结果的
False
,当然,对于每个值类型和枚举,除了
null
类型

而对于VB.NET,我得到了所有值类型和枚举的
False
True
,除了
Nullable
类型,以及
ValueType
[Enum]
返回
False
False
,因为您不能有
ValueType?
[Enum]?
。使用
选项Strict Off
对象
会导致延迟绑定,并在运行时无法找到任何重载,但第二个结果是
False
,这也是因为您不能拥有
对象?

为完整起见,
Nullable
类型按预期返回两种语言的
True
True

C#正在做一些不同的事情(假设我的测试是正确的)这一事实证实了对C#“更好的转换”检查的引用是错误的(或者至少被误读了——C#没有做被解释为VB.NET为什么要做它正在做的事情的事情)

然而,我同意这个问题可能与隐式转换到
Nullable(Of T)
有关,并且在某种程度上比隐式转换到
ValueType
的优先级更高

这是我的LINQPad 4“查询”(C#程序):

void Main()
{
Test.Test();
}
//在此处定义其他方法和类
静态类测试
{
静态布尔为空(此值类型为obj)
{
返回false;
}
静态bool可为空(此T?obj),其中T:struct
{
返回true;
}
公共静态无效测试()
{
int x=42;
bool result1=x.IsNullable();
bool result2=IsNullable(x);
结果1.转储(“结果1”);
结果2.转储(“结果2”);
}
}

您的问题不清楚“您可能认为Test sub中对IsNullable的两个调用都会导致使用相同的重载,实际上它们都使用不同的重载。”我在代码中添加了一些注释。希望这能把事情弄清楚。这不是CLR决定的,而是VB.NET编译器,你的链接是C版本。尽管如此,它可能比@MarkHurd更可读,这是编译器的一个优点。感谢您的澄清。顺便说一句,与
ValueType
进行比较的问题在于没有为
ValueType
定义
=
,而不是无法进行隐式转换。顺便说一句,请注意在两种语言中引用
ValueType?
时出现的错误:-)我注意到这一点在VB.NET 14/C 6中没有改变(VS2015)。因此,我假设微软已经决定这是两种语言在这里不同的一个特性。(我还注意到上面提到的错误消息的VB.NET版本信息更丰富,但两者都感觉“有趣”。)不,我现在相当确定这仍然是一个C错误:C选择了一个
IsNullable(this int?obj)
重载,如果它被定义的话(当然,VB.NET也是如此)。(当
T?
重载仍然可用时,这两种语言都称之为不明确。)
    Dim y As New Nullable(Of Integer)
    y.IsNullable()
    ' 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)