3

如果“== 运算符未定义”会发生什么?

例子:

class a
{
    int variable = 0;
}
class b
{
    void proc()
    {
        a ref1 = new a();
        a ref2 = new a();
        bool cmp1 = ref1 == ref2;//?
        bool cmp2 = ref1 == ref1;//?
    }
}

使用结构时会有所不同吗?

编组的 ( System.Runtime.Remoting.*) 对象(单例)怎么样?

4

4 回答 4

4

对于用户定义的值类型,您的代码将无法编译。

具体来说,它会导致编译失败并出现以下错误:“运算符'=='不能应用于'a'和'a'类型的操作数”。

“== 和 != 运算符不能对结构进行操作,除非结构显式重载它们。”

你必须超载他们两个。您很可能不想Equals()在您的方法中使用默认值,因为 “...对于结构,Object.Equals(Object) 的默认实现(这是 System.ValueType 中的覆盖版本)通过使用执行值相等检查反射来比较类型中每个字段的值。当实现者覆盖结构中的虚拟 Equals 方法时,目的是提供一种更有效的方法来执行值相等检查,并可选择将比较基于结构的字段或属性。”

对于用户定义的引用类型(简化的情况,如 OP 的示例):

“== 和 != 运算符可以与类一起使用,即使类没有重载它们。但是,默认行为是执行引用相等检查。在类中,如果重载 Equals 方法,则应该重载== 和 != 运算符,但这不是必需的。”

如果您不重载运算符,则很可能只有一个引用相等测试。

“简化案例”,因为运算符重载决议可能会选择另一个实现而不是默认的.

//Minimal example, for demonstration only.
//No Equals(), GetHaschode() overload, no IEquatable<T>, null checks, etc..
class Program
{
    static void Main()
    {

        MyMoreDerived a = new MyMoreDerived() { fbase = 1, fderived = 3 };
        MyMoreDerived b = new MyMoreDerived() { fbase = 2, fderived = 3 };

        //Even though MyMoreDerived does not overload the operators, this
        //will succeed - the definition in MyDerived will be used.
        if (a == b)
        {
            //Reached, because the operator in MyDerived is used.
            Console.WriteLine("MyDerived operator used: a == b");
        }

        a.fderived = 2;
        b.fbase = 1;
        //a => {1, 2} 
        //b => {1, 3}
        //Since 2 != 3, the operator in MyDerived would return false.
        //However only the operator in MyBase will be used.
        if ((MyBase)a == (MyBase)b)
        {
            //Reached, because the operator in MyBase is used.
            Console.WriteLine("MyBase operator used: a == b");
        }

        b.fderived = 2;
        //a => {1, 2} 
        //b => {1, 2}
        //Now both operator definitions would compare equal,
        //however they are not used.
        if ((object)a != (object)b)
        {
            //Reached, because the default implementation is used
            //and the references are not equal.
            Console.WriteLine("Default operator used: a != b");
        }

    }

    class MyBase
    {
        public int fbase;

        public static bool operator ==(MyBase x, MyBase y)
        {
            return x.fbase == y.fbase;
        }

        public static bool operator !=(MyBase x, MyBase y)
        {
            return x.fbase != y.fbase;
        }

    }

    class MyDerived : MyBase
    {
        public int fderived;

        public static bool operator ==(MyDerived x, MyDerived y)
        {
            return x.fderived == y.fderived;
        }

        public static bool operator !=(MyDerived x, MyDerived y)
        {
            return x.fderived != y.fderived;
        }

    }

    class MyMoreDerived : MyDerived
    {
    }

}

单例在引用类型的上下文中最有意义,它们的目的是返回一个特定的实例。我无法想象引用相同但对象与自身不“相等”的合理情况。

即使使用远程处理,最好将操作合同与数据合同分开。前者通常由MarshalByRefObject服务器端的 s 实现——实现由接口定义的操作——而后者则使用按值编组的数据/消息类,并且可能由客户端和服务器共享。如果重载数据类中的运算符,这可能不是什么大问题。但是,我相信这些不应该引用/调用远程对象。

即使您提供了一个使操作员过载的自定义客户端代理,恕我直言,将远程调用隐藏在操作员后面也是一种非常糟糕的做法和调试==噩梦!=。(如果我理解你的意图,那我不确定。)

于 2010-03-20T14:12:39.683 回答
1

它可能会比较指针“a”和“b”,它们是否指向内存中的同一个对象。

如果您需要比较这些对象的字段,则必须定义比较器函数。

您需要从 IComparable 接口继承并定义 CompareTo 方法。

看这里:IComparable 接口

于 2010-03-20T13:48:37.113 回答
1

来自 MSDN:

对于预定义的值类型,相等运算符 (==) 如果其操作数的值相等则返回 true,否则返回 false。对于字符串以外的引用类型,== 如果它的两个操作数引用同一个对象,则返回 true。对于字符串类型,== 比较字符串的值。

于 2010-03-20T13:50:01.510 回答
1

当 == 未被覆盖时,我相信它会比较引用,检查它们是否是同一个对象。

例子:

MyClass a = new MyClass(1);
MyClass b = new MyClass(1);
MyClass c = a;

if (a == b) // false
    ...
if (a == c) // true
    ...

因此,在您上面的代码中, cmp1 为假,但 cmp2 为真

但是,对于用户定义的值类型,它会比较类型的实际值。

于 2010-03-20T13:51:14.600 回答