如果“==运算符未定义”会发生什么?
示例:
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.*
)对象(单身人士)怎么样?
答案 0 :(得分:4)
对于用户定义的值类型,您的代码将无法编译。
具体来说,编译失败会出现以下错误:“运算符'=='不能应用于'a'和'a'类型的操作数。
"The == and != operators cannot operate on a struct unless the struct explicitly overloads them."
你必须重载both of them。您很可能不希望在方法中使用默认的Equals()
,因为
“...对于结构体,Object.Equals(Object)的默认实现(它是System.ValueType中的重写版本)通过使用反射来比较类型中每个字段的值来执行值相等性检查。当实现者覆盖stuct中的虚拟Equals方法时,目的是提供一种更有效的方法来执行值相等性检查,并可选择将结果基于struct的一个或多个字段的属性。“
对于用户定义的引用类型(简化情况,如OP的示例中所示):
如果不重载运算符,很可能只有参考相等性测试。
“简化案例”,因为operator overload resolution可能会选择其他实施而不是default。
//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
实现 - 实现接口定义的操作 - 后者的数据/消息类由值封送,可能由客户端和服务器共享。如果重载数据类中的运算符,这可能不是一个大问题。但是,我相信这些不应该引用/调用远程对象。
即使您提供了一个使运营商超载的自定义客户端代理,但是隐藏在==
和!=
运营商后面的远程处理呼叫是一种非常糟糕的做法和调试噩梦。
(如果我理解你的意图,我不确定。)
答案 1 :(得分:1)
它可能会比较指针'a'和'b',无论它们指向内存中的同一个对象。
如果需要比较这些对象的字段,则必须定义比较器函数。
您需要继承IComparable接口并定义CompareTo方法。
答案 2 :(得分:1)
来自MSDN:
对于预定义的值类型,如果操作数的值相等,则等于运算符(==)返回true,否则返回false。 对于string以外的引用类型,如果其两个操作数引用同一个对象,则==返回true。对于字符串类型,==比较字符串的值。
答案 3 :(得分:1)
当==未被覆盖时,我相信它会比较引用,检查它们是否是同一个对象。
示例:
MyClass a = new MyClass(1);
MyClass b = new MyClass(1);
MyClass c = a;
if (a == b) // false
...
if (a == c) // true
...
因此,在上面的代码中,cmp1将为false,但cmp2将为true
但是,对于用户定义的值类型,它会比较类型的实际值。