2008-12-03 36 views
8

Duplicar posible:
Can’t operator == be applied to generic types in C#?¿Cómo comparar dos elementos del mismo tipo genérico sin restricciones para la igualdad?

Tengo la siguiente clase genérica y el compilador se queja de que "Operator '!=' cannot be applied to operands of type 'TValue' and 'TValue'" (ver CS0019):

public class Example<TValue> 
{ 
    private TValue _value; 
    public TValue Value 
    { 
     get { return _value; } 
     set 
     { 
      if (_value != value) // <<-- ERROR 
      { 
       _value= value; 
       OnPropertyChanged("Value"); 
      } 
     } 
    } 
} 

Si yo constriñe TValue a class, podría usar Object.Equals(). Como necesito esto para ambas estructuras y clases, estaría muy feliz si pudiera evitar eso.

Entonces la pregunta es, ¿cómo puedo comparar dos elementos del mismo tipo genérico pero sin restricciones para la igualdad?

+2

¿Por qué no puede usar .Equals para los tipos de valor? –

+0

De manera predeterminada, si llama a "object.Equals (a, b)" en los tipos de referencia, se llamará a "object.ReferenceEquals (a, b)". – TcKs

+0

@TcKs: de forma predeterminada, no puede estar seguro de si Igual ha sido anulado en una clase derivada. – leppie

Respuesta

12

Por favor, intente algo como esto?

public class Example<TValue> 
{ 
    private TValue _value; 
    public TValue Value 
    { 
     get { return _value; } 
     set 
     { 

      if (!object.Equals(_value, value)) 
      { 
       _value = value; 
       OnPropertyChanged("Value"); 
      } 
     } 
    } 
} 
+0

http://msdn.microsoft.com/en-us/library/w4hkze5k.aspx dice que, por defecto, los tipos de valores se compararán en modo bit, de lo contrario se utiliza el método Equals(). Eso es lo que estaba buscando. –

+4

Tenga en cuenta que esto incurrirá en penalizaciones de boxeo para los tipos de valores. –

2
  • Iguales() para los tipos de valor
  • ReferenceEquals() para los tipos de referencia
+1

Prefiero evitar tener que reflexionar o distinguir los dos casos. Actualmente estoy usando una base abstracta e implemento estos bits dos veces: -/ –

+0

¿Qué reflexión estás usando? Hacer un tipo de (TValue) es una constante de tiempo de compilación, y verificar ese tipo realmente no le costará nada. – leppie

0

creo que el operador != no puede aplicarse aquí porque hay casos en los que no se puede utilizar. Por ejemplo, != no se puede usar para comparar estructuras, a menos que los operadores de comparación (==!=) estén sobrecargados.

Por supuesto, puede comparar estructuras de lenguaje, como int != int, pero no estoy seguro de cómo se implementa esto.

Así, porque TValue puede ser una estructura personalizada struct, no puede usar el operador !=.

+0

Sí, esa era mi comprensión de CS0019 también. –

1

¿Es IComparable una opción?

public class Example<TValue> where TValue: IComparable 
{ 
    private TValue _value; 
    public TValue Value 
    { 
     get { return _value; } 
     set 
     { 

      if (_value.CompareTo(value) != 0) 
      { 
       _value = value; 
       OnPropertyChanged("Value"); 
      } 
     } 
    } 
} 
7

tres opciones:

  • Restringir TValue para implementar IEquatable<TValue> y luego llaman x.Equals(y)
  • tomar otro parámetro de tipo IEqualityComparer<TValue> y el uso que
  • Uso EqualityComparer<TValue>.Default para realizar las comparaciones

Siempre puede mezclar y combinar las opciones 2 y 3, por supuesto, de manera predeterminada al comparador predeterminado, pero también permite que se proporcione uno específico.

0
public static bool operator ==(EntityBase<T> entity1, EntityBase<T> entity2) 
     { 
      if ((object)entity1 == null && (object)entity2 == null) 
      { 
       return true; 
      } 

      if ((object)entity1 == null || (object)entity2 == null) 
      { 
       return false; 
      } 

      if (Comparer<T>.Default.Compare(entity1.Id, entity2.Id) != 0) 
      { 
       return false; 
      } 

      return true; 
     } 
Cuestiones relacionadas