Pregunta

Pensé que este método era válido pero estaba equivocado:

static void Equals<T>(T x, T y)
{
    return x == y;    //operator == can't be applied to type T
}

Después de leer la especificación (§7.2.4 en v3.0 y §7.3.4 en v4.0):

7.2.4 Resolución de sobrecarga del operador binario

Una operación de la forma X op y, donde OP es un operador binario sobrecargable, X es una expresión del tipo X, y y es una expresión de tipo Y, se procesa de la siguiente manera:

  • Se determina el conjunto de operadores candidatos definidos por el usuario proporcionados por X e Y para el operador de operación OP (X, Y). El conjunto consiste en la unión de los operadores candidatos proporcionados por X y los operadores candidatos proporcionados por Y, cada uno determinado utilizando las reglas de §7.2.5. Si X e Y son del mismo tipo, o si X e Y se derivan de un tipo de base común, entonces los operadores candidatos compartidos solo ocurren en el conjunto combinado una vez.

  • Si el conjunto de operadores definidos por el usuario candidato no está vacío, entonces esto se convierte en el conjunto de operadores candidatos para la operación. De lo contrario, las implementaciones de operadores binarios predefinidos, incluidas sus formularios levantados, se convierten en el conjunto de operadores candidatos para la operación. Las implementaciones predefinidas de un operador dado se especifican en la descripción del operador (§7.7 a §7.11).

  • Las reglas de resolución de sobrecarga de §7.4.3 se aplican al conjunto de operadores candidatos para seleccionar el mejor operador con respecto a la lista de argumentos (X, Y), y este operador se convierte en el resultado del proceso de resolución de sobrecarga. Si la resolución de sobrecarga no puede seleccionar un solo mejor operador, se produce un error de tiempo de compilación.

En el paso 2, creo que se debe aplicar esta implementación predefinida:

bool operator ==(object x, object y);
bool operator !=(object x, object y);

ya que todo en C# deriva del objeto. ¿Cómo puede ocurrir un error de tiempo de compilación en el paso 3? No creo que sea posible que "la resolución de sobrecarga no se seleccione" en este caso.

EDITAR La pregunta me vino a la mente cuando estaba implementando algo como esto:

class EnumComparer<TEnum> : IEqualityComparer<TEnum>
{
    public bool Equals(TEnum x, TEnum y)
    {
        return x == y;
    }
    public int GetHashCode(TEnum obj)
    {
        return (int)obj;
    }
}

Me temo que necesito construir una expresión e invocarla dinámicamente en Equals método.

¿Fue útil?

Solución

Bien por ti por leer las especificaciones, pero dejaste de leer demasiado pronto. Si hubieras leído más, habrías llegado a este bit:


Los operadores de igualdad de tipo de referencia predefinidos requieren uno de los siguientes:

  • Ambos operandos son un valor de un tipo que se sabe que es un tipo de referencia o el nulo literal. Además, existe una conversión de referencia explícita desde el tipo de operando al tipo de otro operando.

  • Un operando es un valor de tipo t donde t es un tipo parámetro y el otro operando es el literal nulo. Además, T no tiene la restricción de tipo de valor.

A menos que una de estas condiciones sea verdadera, se produce un error de tiempo de enlace. (*)


El error no es de la resolución de sobrecarga; El error es que la resolución de sobrecarga habría elegido el operador de igualdad de tipo de referencia predefinido, y no tiene tipos de referencia.

Considere su código. ¿Qué impide que T sea un tipo de valor sin un operador de igualdad definido en él? Nada. Supongamos que volvimos a caer a la versión del objeto; Ambos operandos se encerrarían en diferentes ubicaciones y, por lo tanto, serían referencia-inyectales, incluso si tuvieran el mismo contenido. Como eso es lento, confuso e incorrecto, es ilegal incluso intentarlo.

¿Por qué intentas hacer esto en primer lugar? Si su método funcionara, lo cual no es así, entonces su método sería peor que simplemente usar == en primer lugar. ¿Cuál es el valor que pretende agregar al mundo con este método?


(*) He informado el error gramatical en esta oración a los mantenedores de especificaciones.

Otros consejos

Eso posiblemente funcionaría si supiera que where T : class, haciendo una comparación de referencia. Los operadores generalmente tienen muy poco apoyo con los genéricos, pero hay soluciones. Ofertas de Miscutil Soporte indirecto para los operadores en genéricos, de lo contrario EqualityComparer<T>.Default.Equals(x,y) es una buena opción.

Me gusta usar EqualityComparer<T>.Default para esto.

Se basa en el anulado Equals método, pero usa IEquatable<T> Cuando esté disponible, evitando el boxeo en los tipos de valor implementándolo.

EqualityComparer<T>.Default.Equals(x, y)

usar .Equals() método y asegúrese de que el T implementar IComparable

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top