为什么n.GetHashCode()工作,但n.GetType()抛出和异常? [英] why does n.GetHashCode() work but n.GetType() throws and exception?

查看:80
本文介绍了为什么n.GetHashCode()工作,但n.GetType()抛出和异常?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我自学C#(我不知道很多还没有)。在这个简单的例子:

I am teaching myself C# (I don't know much yet). In this simple example:

bool?          n = null;

Console.WriteLine("n               = {0}", n);
Console.WriteLine("n.ToString()    = {0}", n.ToString());
Console.WriteLine("n.GetHashCode() = {0}", n.GetHashCode());

// this next statement causes a run time exception

Console.WriteLine("n.GetType()     = {0}", n.GetType());



直观地我明白了为什么对GetType()方法会抛出异常。实例n为null进行n.GetHashCode()和toString()方法时可能会解释说,但是,为什么不让我得到一个异常出于同样的原因?

Intuitively I understand why the GetType() method would throw an exception. The instance n is null which would explain that but, why don't I get an exception for the same reason when using n.GetHashCode() and ToString() ?

感谢你的帮助,

约翰。

推荐答案

的GetHashCode()可空< T> :当它被称为一个可空< T> 值时,可空< T> 实施时,不任何拳击。

GetHashCode() is a virtual method overridden in Nullable<T>: when it's called on a Nullable<T> value, the Nullable<T> implementation is used, without any boxing.

的GetType()的虚方法,这意味着当它的名字,其值将首先装箱......和拳击一个空可为空值空引用的结果 - 因此例外。我们可以从IL看到这一点:

GetType() isn't a virtual method, which means that when it's called, the value is boxed first... and boxing a "null" nullable value results in a null reference - hence the exception. We can see this from the IL:

static void Main()
{
    bool? x = null;
    Type t = x.GetType();
}



被编译为:

is compiled to:

.method private hidebysig static void Main() cil managed
{
    .entrypoint
    .maxstack 1
    .locals init (
        [0] valuetype [mscorlib]System.Nullable`1<bool> nullable,
        [1] class [mscorlib]System.Type 'type')
    L_0000: nop 
    L_0001: ldloca.s nullable
    L_0003: initobj [mscorlib]System.Nullable`1<bool>
    L_0009: ldloc.0 
    L_000a: box [mscorlib]System.Nullable`1<bool>
    L_000f: callvirt instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
    L_0014: stloc.1 
    L_0015: ret 
}

在这里最重要的一点是L_000a:在指令在L_000f的 callvirt 指令。

The important bit here is L_000a: the box instruction before the callvirt instruction at L_000f.

现在比较,与同等代码调用的GetHashCode

Now compare that with the equivalent code calling GetHashCode:

static void Main()
{
    bool? x = null;
    int hash = x.GetHashCode();
}



编译为:

compiles to:

.method private hidebysig static void Main() cil managed
{
    .entrypoint
    .maxstack 1
    .locals init (
        [0] valuetype [mscorlib]System.Nullable`1<bool> nullable,
        [1] int32 num)
    L_0000: nop 
    L_0001: ldloca.s nullable
    L_0003: initobj [mscorlib]System.Nullable`1<bool>
    L_0009: ldloca.s nullable
    L_000b: constrained [mscorlib]System.Nullable`1<bool>
    L_0011: callvirt instance int32 [mscorlib]System.Object::GetHashCode()
    L_0016: stloc.1 
    L_0017: ret 
}

这一次,我们有一个受限指令/前前缀 callvirt ,这基本上意味着你并不需要,当你调用虚方法框。从 OpCodes.Constrained 文件:

This time we have a constrained instruction/prefix before callvirt, which essentially means "You don't need to box when you call the virtual method." From the OpCodes.Constrained documentation:

的约束前缀被设计为允许在独立的是否thisType一种统一的方式来进行callvirt指令是值类型或引用类型。

The constrained prefix is designed to allow callvirt instructions to be made in a uniform way independent of whether thisType is a value type or a reference type.

(点击此链接了解更多信息。)

(Follow the link for more information.)

需要注意的是空值的拳击类型也工作方式意味着,即使一个的非空的价值,你不会得到可空< T> 。例如,考虑:

Note that the way boxing of nullable value types work also means that even for a non-null value, you won't get Nullable<T>. For example consider:

int? x = 10;
Type t = x.GetType();
Console.WriteLine(t == typeof(int?)); // Prints False
Console.WriteLine(t == typeof(int)); // Prints True



所以你走出类型是的非空的类型有关。到 object.GetType()的调用将的从不的返回可空< T> 键入

So the type you get out is the non-nullable type involved. A call to object.GetType() will never return a Nullable<T> type.

这篇关于为什么n.GetHashCode()工作,但n.GetType()抛出和异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆