C# 运算符==在基中,在派生中等于
我有一个通过引用进行比较的基类和一个通过值进行比较的派生类(仅显示此处相关的行): 在这里最好做什么?我可以使用暴力解决方案来禁用警告,但我想检查并确保没有更优雅的解决方案,我缺少一些习惯用法C# 运算符==在基中,在派生中等于,c#,.net,operator-overloading,equality,C#,.net,Operator Overloading,Equality,我有一个通过引用进行比较的基类和一个通过值进行比较的派生类(仅显示此处相关的行): 在这里最好做什么?我可以使用暴力解决方案来禁用警告,但我想检查并确保没有更优雅的解决方案,我缺少一些习惯用法 我有一个通过引用进行比较的基类和一个派生类 通过值进行比较(仅显示相关的行 这里) 您当前的实现不一定执行引用相等;它实际上调用了等于的潜在重载 因此派生类重写等于,但基类必须重载== 我不明白为什么,如果基类重写等于,那么需要在基类中重载==已执行引用比较,因为静态==(对象,对象)在编译时解析 。。。
我有一个通过引用进行比较的基类和一个派生类 通过值进行比较(仅显示相关的行 这里) 您当前的实现不一定执行引用相等;它实际上调用了
等于的潜在重载
因此派生类重写等于,但基类必须重载==
我不明白为什么,如果基类重写等于
,那么需要在基类中重载=
<如果未定义重载,则代码>=
已执行引用比较,因为静态==(对象,对象)
在编译时解析
。。。在a和b被声明为术语,但实际上指向复合术语的上下文中,a==b是可能的,而且确实是可能的
调用=
操作符时,a
和b
的实际类型是什么并不重要=
是一个静态方法,因此将根据参数的引用类型进行解析:
object aString = "Hello";
object theSameString = new string(new[] { 'H', 'e', 'l', 'l', 'o' }); //to avoid string interning
var referenceEquals = aString == theSameString; //false: object == object
var valueEquals = (string)aString == (string)theSameString; //true: string == string
现在我了解到,如果a
和b
是Term
而不是子类,那么在调用==
时,您正试图执行引用相等,否则执行潜在值相等
老实说,这似乎相当令人困惑。我建议让=
始终执行引用相等(不要重载),如果需要潜在的值相等,请使用=
并记录类或代码以明确此行为。“我有一个通过引用进行比较的基类”-这不是基类所做的。它调用Equals
,可以在派生类中重写。听起来您应该潜在地重写Equals
作为基类中的抽象方法,以强制所有子类提供实现。(与GetHashCode相同。)(假设您可以将术语
类抽象化,这似乎很可能。)@JonSkeet当然,我可以将术语
抽象化,并将原子术语
派生类通过引用进行比较。在这种情况下,AtomicTerm.Equals
是必需的,但是可以是一个只返回ReferenceEquals(this,o)
?@JonSkeet但是,在这种情况下,我该为AtomicTerm.GetHashCode
做些什么呢?有没有一种类似的简便方法来调用通过引用工作的默认版本?您可以使用System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(object)
,但是只有一种术语具有引用相等性,而其他所有术语都具有值相等性,这很奇怪。。。还请注意,您的运算符可以简化为调用等于(a,b)
。它处理空值。
Term.cs(40,11): warning CS0660: 'Term' defines operator == or operator != but does not override Object.Equals(object o)
object aString = "Hello";
object theSameString = new string(new[] { 'H', 'e', 'l', 'l', 'o' }); //to avoid string interning
var referenceEquals = aString == theSameString; //false: object == object
var valueEquals = (string)aString == (string)theSameString; //true: string == string