Sobrecarga del operador con programación basada en interfaz en C #

Fond

Estoy utilizando programación basada en interfaz en un proyecto actual y me he encontrado con un problema al sobrecargar a los operadores (específicamente los operadores de Igualdad y Desigualdad).

Suposiciones Estoy usando C # 3.0, .NET 3.5 y Visual Studio 2008

UPDATE - ¡La siguiente suposición era falsa!

Requerir todas las comparaciones para usar Equals en lugar de operator == no es una solución viable, especialmente al pasar sus tipos a bibliotecas (como Colecciones).

La razón por la que me preocupaba requerir que se usara Equals en lugar del operador == es que no pude encontrar en ninguna parte de las pautas de .NET que dijera que usaría Equals en lugar del operador == o incluso sugerirlo. Sin embargo, después de volver a leerGuidelines para anular iguales y operador == He encontrado esto:

Por defecto, el operador == prueba la igualdad de referencia al determinar si dos referencias indican el mismo objeto. Por lo tanto, los tipos de referencia no tienen que implementar el operador == para obtener esta funcionalidad. Cuando un tipo es inmutable, es decir, los datos contenidos en la instancia no se pueden cambiar, sobrecargar el operador == para comparar la igualdad de valores en lugar de la igualdad de referencia puede ser útil porque, como objetos inmutables, se pueden considerar iguales siempre ya que tienen el mismo valor No es una buena idea anular el operador == en tipos no inmutables.

y esto Interfaz ecológica

La interfaz IEquatable es utilizada por objetos de colección genéricos como Dictionary, List y LinkedList cuando se prueba la igualdad en métodos como Contains, IndexOf, LastIndexOf y Remove. Debe implementarse para cualquier objeto que pueda almacenarse en una colección genérica.

ContraintsCualquier solución no debe exigir que los objetos pasen de sus interfaces a sus tipos concretos.ProblemCuando alguna de las partes del operador == sean una interfaz, ninguna firma de método de sobrecarga de operador == de los tipos concretos subyacentes coincidirá y, por lo tanto, se llamará al método predeterminado Object operator ==. Cuando se sobrecarga un operador en una clase, al menos uno de los parámetros del operador binario debe ser del tipo contenedor, de lo contrario se genera un error de compilación (Error BC33021http: //msdn.microsoft.com/en-us/library/watt39ff.asp) No es posible especificar la implementación en una interfaz

Vea el Código y la Salida a continuación que demuestran el problema.

Pregunt

¿Cómo proporciona sobrecargas de operador adecuadas para sus clases cuando utiliza la programación basada en interfaz?

Referencias

== Operador (Referencia de C #)

Para los tipos de valores predefinidos, el operador de igualdad (==) devuelve verdadero si los valores de sus operandos son iguales, de lo contrario, falso. Para los tipos de referencia que no sean cadenas, == devuelve verdadero si sus dos operandos se refieren al mismo objeto. Para el tipo de cadena, == compara los valores de las cadenas.

Ver tambiéCódig
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.");
            }
        }
    }
}
Salid
Address operator== overload called
Equal with both sides cast.

Respuestas a la pregunta(2)

Su respuesta a la pregunta