比较结构为null [英] Comparing structs to null

查看:108
本文介绍了比较结构为null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可能重复:结果
C#与还好比较值类型为null

我工作在多线程环境中的Windows应用程序,有时会得到异常调用或BeginInvoke可直到窗口句柄已创建不能在一个控件调用。所以,我计算过,我只是添加此行代码:

I was working on a windows app in a multithreaded environment and would sometimes get the exception "Invoke or BeginInvoke cannot be called on a control until the window handle has been created." So I figured that I'd just add this line of code:

if(this.Handle != null)
{
   //BeginInvokeCode
}

但是,这并没有解决问题。所以,我挖了一个远一点,并意识到的IntPtr(即Form.Handle的类型)是不能为空的是一个结构。这是工作的修复:

But that didn't solve the problem. So I dug a little further, and realized that IntPtr (the type that Form.Handle is) is a struct which can't be nullable. This was the fix that worked:

if(this.Handle != IntPtr.Zero)
{
   //BeginInvokeCode
}

于是打我,为什么它甚至当编译我检查它空?所以我决定自己试试吧:

So then it hit me, why did it even compile when I was checking it for null? So I decided to try it myself:

    public struct Foo { }

和则:

    static void Main(string[] args)
    {
        Foo f = new Foo();
        if (f == null) { }
    }



果然它没有编译说,错误1操作'=='不能应用于类型为ConsoleApplication1.Foo'和''的操作数。好了,然后我就开始寻找为IntPtr的元数据和开始添加的一切我美孚结构,这是那里的IntPtr的结构(ISerializable的,标记有ComVisible特性),但没有任何帮助。 !最后,当我加==的运算符重载和=,它的工作:

and sure enough it didn't compile saying that "Error 1 Operator '==' cannot be applied to operands of type 'ConsoleApplication1.Foo' and ''". Ok, so then I started looking at the metadata for IntPtr and started adding everything to my Foo struct that was there in the IntPtr struct (ISerializable, ComVisible) but nothing helped. Finally, when I added the operator overloading of == and !=, it worked:

[Serializable]
[ComVisible(true)]
public struct Foo : ISerializable
{
    #region ISerializable Members

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        throw new NotImplementedException();
    }

    #endregion

    public override bool Equals(object obj)
    {
        return base.Equals(obj);
    }

    public override int GetHashCode()
    {
        return base.GetHashCode();
    }

    public static bool operator ==(Foo f1, Foo f2) { return false; }
    public static bool operator !=(Foo f1, Foo f2) { return false; }
}

这最后编译:

    static void Main(string[] args)
    {
        Foo f = new Foo();
        if (f == null) { }
    }



我的问题是为什么?为什么如果重写==和!=你允许比较空?该参数==和!=是Foo类型哪些不可为空的是,为什么是这让突然?

My question is why? Why if you override == and != are you allowed to compare to null? The parameters to == and != are still of type Foo which aren't nullable, so why's this allowed all of a sudden?

推荐答案

它看起来像问题是,当MS推出可空类型,他们把它让每一个结构是隐式可转换到其可空类型(富?),所以代码

It looks like the issue is that when MS introduced nullable types, they made it so that every struct is implicitly convertable to its nullable type (foo?), so the code

if( f == null)

等同于

if ( (Nullable<foo>)f == (Nullable<foo>)null) 

由于MSDN指出,任何用户定义的运营商存在的价值类型也可以通过可空类型,使用时你ovveride 运算符== ,你让隐式转换为编译,因为你现在有一个用户定义的== - 。给你免费可空过载

Since MSDN states that "any user-defined operators that exist for value types may also be used by nullable types", when you ovveride operator==, you allow that implicit cast to compile, as you now have a user-defined == -- giving you the nullable overload for free.

旁白:

好像在你的例子,有一些编译器优化
是由连暗示有一个测试的编译器发出的唯一事情是这样的IL:

Seems like in your example, there is some compiler optimization The only thing that is emitted by the compiler that even hints there was a test is this IL:

ldc.i4.0
ldc.i4.0
ceq
stloc.1   //where there is an unused boolean local

请注意,如果你改变主要为

Note that if you change main to

Foo f = new Foo();
object b = null;
if (f == b) { Console.WriteLine("?"); }



它不再编译。但是,如果你框结构:

It no longer compiles. But if you box the struct:

Foo f = new Foo();
object b = null;
if ((object)f == b) { Console.WriteLine("?"); }

如果编译,发出IL,并运行如预期(该结构是不能为null);

if compiles, emits IL, and runs as expected (the struct is never null);

这篇关于比较结构为null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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