最佳答案
我在一个当前项目中使用基于接口的编程,在重载操作符(特别是 EquityandIneQuality 操作符)时遇到了问题。
更新-下面的假设是错误的!
之所以要求使用 Equals 而不是操作符 = = ,是因为在。NET 指导方针,它声明将使用 Equals 而不是操作符 = = ,甚至建议使用 Equals。然而,重读 重写等式和运算符的准则 = = 后,我发现:
默认情况下,运算符 = = 通过确定两个引用是否指示同一个对象来测试引用相等性。因此,引用类型不必实现 Operator = = 来获得这个功能。当一个类型是不可变的,也就是说,包含在实例中的数据不能更改时,重载运算符 = = 来比较值相等而不是引用相等是有用的,因为作为不可变对象,只要它们具有相同的值,就可以认为它们是相同的。在非不可变类型中覆盖运算符 = = 不是一个好主意。
还有这个 等效接口
当测试诸如 Contain、 IndexOf、 LastIndexOf 和 delete 等方法中的相等性时,通用集合对象(如 Dictionary、 List 和 LinkedList)可以使用 IEquable 接口。它应该针对可能存储在泛型集合中的任何对象实现。
请参阅下面的代码和输出来演示这个问题。
在使用基于接口的编程时,如何为类提供适当的运算符重载?
对于预定义的值类型,如果其操作数的值相等,则相等运算符(= =)返回 true,否则返回 false。对于字符串以外的引用类型,如果 = = 的两个操作数引用同一个对象,则 = = 返回 true。对于字符串类型,= = 比较字符串的值。
using System;
namespace OperatorOverloadsWithInterfaces
{
public interface IAddress : IEquatable<IAddress>
{
string StreetName { get; set; }
string City { get; set; }
string State { get; set; }
}
public class Address : IAddress
{
private string _streetName;
private string _city;
private string _state;
public Address(string city, string state, string streetName)
{
City = city;
State = state;
StreetName = streetName;
}
#region IAddress Members
public virtual string StreetName
{
get { return _streetName; }
set { _streetName = value; }
}
public virtual string City
{
get { return _city; }
set { _city = value; }
}
public virtual string State
{
get { return _state; }
set { _state = value; }
}
public static bool operator ==(Address lhs, Address rhs)
{
Console.WriteLine("Address operator== overload called.");
// If both sides of the argument are the same instance or null, they are equal
if (Object.ReferenceEquals(lhs, rhs))
{
return true;
}
return lhs.Equals(rhs);
}
public static bool operator !=(Address lhs, Address rhs)
{
return !(lhs == rhs);
}
public override bool Equals(object obj)
{
// Use 'as' rather than a cast to get a null rather an exception
// if the object isn't convertible
Address address = obj as Address;
return this.Equals(address);
}
public override int GetHashCode()
{
string composite = StreetName + City + State;
return composite.GetHashCode();
}
#endregion
#region IEquatable<IAddress> Members
public virtual bool Equals(IAddress other)
{
// Per MSDN documentation, x.Equals(null) should return false
if ((object)other == null)
{
return false;
}
return ((this.City == other.City)
&& (this.State == other.State)
&& (this.StreetName == other.StreetName));
}
#endregion
}
public class Program
{
static void Main(string[] args)
{
IAddress address1 = new Address("seattle", "washington", "Awesome St");
IAddress address2 = new Address("seattle", "washington", "Awesome St");
functionThatComparesAddresses(address1, address2);
Console.Read();
}
public static void functionThatComparesAddresses(IAddress address1, IAddress address2)
{
if (address1 == address2)
{
Console.WriteLine("Equal with the interfaces.");
}
if ((Address)address1 == address2)
{
Console.WriteLine("Equal with Left-hand side cast.");
}
if (address1 == (Address)address2)
{
Console.WriteLine("Equal with Right-hand side cast.");
}
if ((Address)address1 == (Address)address2)
{
Console.WriteLine("Equal with both sides cast.");
}
}
}
}
Address operator== overload called
Equal with both sides cast.