Sobrecarga de operador com programação baseada em interface em C #
Estou usando programação baseada em interface em um projeto atual e tive um problema ao sobrecarregar os operadores (especificamente os operadores de Igualdade e Desigualdade
Premissa Estou usando C # 3.0, .NET 3.5 e Visual Studio 2008UPDATE - A seguinte suposição era falsa!
Exigir que todas as comparações usem Equals em vez de operator == não é uma solução viável, especialmente ao passar seus tipos para bibliotecas (como ColeçõesO motivo pelo qual eu estava preocupado em exigir que o Equals fosse usado em vez do operador == é que não consegui encontrar em nenhum lugar nas diretrizes do .NET que ele declarasse que usaria o Equals em vez do operador == ou até sugerisse. No entanto, após reler Diretrizes para substituir iguais e operador == Encontrei o seguinte:
Por padrão, o operador == testa a igualdade de referência, determinando se duas referências indicam o mesmo objeto. Portanto, os tipos de referência não precisam implementar o operador == para obter essa funcionalidade. Quando um tipo é imutável, ou seja, os dados contidos na instância não podem ser alterados, sobrecarregar o operador == para comparar a igualdade de valor em vez da igualdade de referência pode ser útil porque, como objetos imutáveis, eles podem ser considerados os mesmos desde que como eles têm o mesmo valor. Não é uma boa idéia substituir o operador == em tipos não imutáveis.
e isto Interface Equipável
A interface IEquatable é usada por objetos genéricos de coleção, como Dictionary, List e LinkedList, ao testar a igualdade em métodos como Contains, IndexOf, LastIndexOf e Remove. Ele deve ser implementado para qualquer objeto que possa ser armazenado em uma coleção genéric
Contraints Qualquer solução não deve exigir a conversão dos objetos de suas interfaces para seus tipos de concretProblem Sempre que os dois lados do operador == forem uma interface, nenhuma assinatura do método de sobrecarga do operador == dos tipos de concreto subjacentes corresponderá e, portanto, o método padrão do operador de Objeto == será chamado. Ao sobrecarregar um operador em uma classe, pelo menos um dos parâmetros do operador binário deve ser o tipo que contém, caso contrário, um erro do compilador é gerado (Erro BC33021http: //msdn.microsoft.com/en-us/library/watt39ff.asp) Não é possível especificar a implementação em uma interfaceVeja o código e a saída abaixo demonstrando o problem
QuestãComo você fornece sobrecargas de operador adequadas para suas classes ao usar a programação baseada em interface?
Referência== Operador (referência de C #)
Para tipos de valor predefinidos, o operador de igualdade (==) retornará true se os valores de seus operandos forem iguais, caso contrário, false. Para tipos de referência diferentes de string, == retorna true se seus dois operandos se referem ao mesmo objeto. Para o tipo de string, == compara os valores das strings.
Veja tambéCódigusing 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.");
}
}
}
}
ResultadAddress operator== overload called
Equal with both sides cast.