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