Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/305.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
C# 为什么为方法选择将null强制转换为type有效?_C#_Compile Time Constant - Fatal编程技术网

C# 为什么为方法选择将null强制转换为type有效?

C# 为什么为方法选择将null强制转换为type有效?,c#,compile-time-constant,C#,Compile Time Constant,根据对的回答,空值似乎携带类型信息。其实我也可以用 class Program { static void Method(TypeA a) { Console.Write("Output of Method(TypeA a):"); Console.WriteLine(a); // Prints nothing, on account of the null. } static void Method(TypeB b) {

根据对的回答,空值似乎携带类型信息。其实我也可以用

class Program
{
    static void Method(TypeA a)
    {
        Console.Write("Output of Method(TypeA a):");
        Console.WriteLine(a); // Prints nothing, on account of the null.
    }
    static void Method(TypeB b)
    {
        Console.Write("Output of Method(TypeB b):");
        Console.WriteLine(b); // Also prints nothing, on account of the null.
    }
    static void Main()
    {
        var a = (TypeA)null;
        var b = (TypeB)null;
        Method(a);
        Method(b);
    }
}
class TypeA { }
class TypeB { }
产生

方法(类型a)的输出:
方法(类型b)的输出:


这是怎么回事

当您编写
var
时,编译器将根据您分配的变量来确定变量的类型

通过执行显式(C样式)转换,您可以说“这就是此类型”,并且
var
会拾取该值,从而导致重载按显示的方式工作


赋值“null”对于任何引用类型都是有效的值(当然可以编译),但是类型信息是由cast提供的。

当您编写
var
时,编译器会根据您所赋值的变量来确定变量的类型

通过执行显式(C样式)转换,您可以说“这就是此类型”,并且
var
会拾取该值,从而导致重载按显示的方式工作


赋值“null”对于任何引用类型都是有效的值(当然编译也是如此),但是类型信息是由cast提供的。

否,null本身不携带类型信息。强制转换只是告诉编译器变量
a
b
的类型应该是什么。。。如果没有强制转换,它无法判断,因为
null
可转换为任何引用类型或可为null的类型

然后在重载解析中使用这些变量的类型。不要忘记,这里的选择只是在编译时做出的——它根本不涉及参数的执行时值

您的代码完全等同于:

TypeA a = null;
TypeB b = null;
Method(a);
Method(b);
如果使用动态键入,以便在执行时执行重载解析,则会出现故障:

dynamic foo = (TypeA) null; // Or without the cast. It makes no difference.
Method(foo); // RuntimeBinderException at execution time, due to ambiguity

不,null本身不携带类型信息。强制转换只是告诉编译器变量
a
b
的类型应该是什么。。。如果没有强制转换,它无法判断,因为
null
可转换为任何引用类型或可为null的类型

然后在重载解析中使用这些变量的类型。不要忘记,这里的选择只是在编译时做出的——它根本不涉及参数的执行时值

您的代码完全等同于:

TypeA a = null;
TypeB b = null;
Method(a);
Method(b);
如果使用动态键入,以便在执行时执行重载解析,则会出现故障:

dynamic foo = (TypeA) null; // Or without the cast. It makes no difference.
Method(foo); // RuntimeBinderException at execution time, due to ambiguity
空值似乎携带类型信息

否,变量的类型为
null
只是
null
。调用哪个方法是在编译时确定的。执行此操作时:

var a = (TypeA)null;     
var b = (TypeB)null;
Method(a);
Method(b);
编译器将
Method(a)
绑定到
Method(TypeA)
,因为您在调用中使用了
TypeA
类型的变量。
方法(b)
也是如此。您提到的问题更详细地解释了绑定

要证明
null
不包含类型信息,请添加第三个将方法绑定延迟到运行时的调用:

static void Main()
{
    var a = (TypeA)null;
    var b = (TypeB)null;
    dynamic c = a;
    Method(a);
    Method(b);
    Method(c);   // will throw a `RuntimeBinderException` since the type of c can't be determined at run-time.
}
空值似乎携带类型信息

否,变量的类型为
null
只是
null
。调用哪个方法是在编译时确定的。执行此操作时:

var a = (TypeA)null;     
var b = (TypeB)null;
Method(a);
Method(b);
编译器将
Method(a)
绑定到
Method(TypeA)
,因为您在调用中使用了
TypeA
类型的变量。
方法(b)
也是如此。您提到的问题更详细地解释了绑定

要证明
null
不包含类型信息,请添加第三个将方法绑定延迟到运行时的调用:

static void Main()
{
    var a = (TypeA)null;
    var b = (TypeB)null;
    dynamic c = a;
    Method(a);
    Method(b);
    Method(c);   // will throw a `RuntimeBinderException` since the type of c can't be determined at run-time.
}

虽然呈现的情况很明显,但我偶然发现了一些涉及动态强制转换的奇怪行为。请看下面的程序:

class Base { }
class Child : Base { }

class Program
{
    static void Main(string[] args)
    {
        Base node = GetChild();
        Test((dynamic) node);

        node = GetBase();
        Test((dynamic) node);
    }

    static Child GetChild()
    {
        return null;
    }
    static Base GetBase()
    {
        return null;
    }

    // Guess how many times each method is called..
    static void Test(Base node)
    {
        // Nope!
    }

    static void Test(Child child)
    {
        // It's this one twice.
    }
}
使用.NET reflector检查代码导致崩溃(不明确的匹配),但dotPeek提供了对生成的IL的更详细的了解(在此处反编译):

换句话说,不管类型如何,null对象上的动态强制转换都将自下而上遍历继承树,并在该级别上找到多个类型时放弃。。如上所述,让另一个孩子从孩子继承确实会调用另一个孩子处理程序

class AnotherChild : Child { }

老实说,我认为对空对象进行动态强制转换是非法的,如果每次都这样做会更好。当您进行动态强制转换时,您可能还使用了方法重载;这似乎是一个正在酝酿中的沉默杀手。

虽然案例显而易见,但我偶然发现了一些涉及动态强制转换的奇怪行为。请看下面的程序:

class Base { }
class Child : Base { }

class Program
{
    static void Main(string[] args)
    {
        Base node = GetChild();
        Test((dynamic) node);

        node = GetBase();
        Test((dynamic) node);
    }

    static Child GetChild()
    {
        return null;
    }
    static Base GetBase()
    {
        return null;
    }

    // Guess how many times each method is called..
    static void Test(Base node)
    {
        // Nope!
    }

    static void Test(Child child)
    {
        // It's this one twice.
    }
}
使用.NET reflector检查代码导致崩溃(不明确的匹配),但dotPeek提供了对生成的IL的更详细的了解(在此处反编译):

换句话说,不管类型如何,null对象上的动态强制转换都将自下而上遍历继承树,并在该级别上找到多个类型时放弃。。如上所述,让另一个孩子从孩子继承确实会调用另一个孩子处理程序

class AnotherChild : Child { }
老实说,我认为对空对象进行动态强制转换是非法的,如果每次都这样做会更好。当您进行动态强制转换时,您可能还使用了方法重载;这似乎是一个正在酝酿中的沉默杀手