¿Hay una mejor manera de implementar esta interfaz IEquatable con tipos genéricos
Actualmente tengo una clase que es casi un envoltorio alrededor de un Booleano para representar un valor de algún hardware físico. Tendré otra clase como esta que es doble. A medida que el sistema crece podemos tener tipos más complejos así que quiero que las cosas sean expandibles, pero estoy empezando aquí. Todas estas clases representan valores físicos por lo que necesitan ser ecualables para poder comprobar su validez. Los he implementado hasta ahora:
Tengo una interfaz ISignalValue que implementa IEquatable
public interface ISignalValue : IEquatable
{
public string AssociatedSignal { get; set; }
}
Entonces tengo una clase base genérica que implementa esta interfaz, y de la cual cada Valor de Señal heredará.
public class SignalValue : ISignalValue
{
public readonly T Value;
public SignalValue(T value)
{
Value = value;
}
public string AssociatedSignal { get; set; }
public bool Equals(ISignalValue other)
{
if (Value is IEquatable)
{
return Value.Equals((IEquatable)other);
}
else return false;
}
}
Por último, aquí hay un valor de señal que he implementado.
public class DiscreteValue : SignalValue
{
public DiscreteValue(bool value) : base(value){}
public double ToDouble() => Value ? 1 : 0;
public static implicit operator DiscreteValue(bool b) => new DiscreteValue(b);
public static implicit operator bool(DiscreteValue d) => d.Value;
}
Creé a los operadores implícitos porque quiero que el usuario de la clase pueda hacer cosas como
discreteValue.Equals(true)
así que no necesitan hacer cosas como discreteValue.Equals(new DiscreteValue(true))
Todo esto funciona bien. Pero lo que me pregunto es, ¿hay una mejor manera de implementar esto, más específicamente, la interfaz IEquatable? Por alguna razón, definir un Valor Discreto como DiscreteValue : SignalValue
Parece extraño. Un DiscreteValue es un Valor de Señal del tipo DiscreteValue? Se siente como usar la palabra en una definición de la palabra misma.
Mi pensamiento inicial era definir un Valor Discreta como DiscreteValue: SignalValue
que tiene más sentido. Pero el problema con eso es, cuando hago algo como lo siguiente fallará porque uno es IEquatable
y el otro es IEquatable
.
Tengo esta excepción:
Incapaz de lanzar objeto de tipo '-omitted-. Valores.DescreteValue' para escribir 'System.IEquatable`1[System.Boolean] '
public bool Equals(ISignalValue other)
{
if (Value is IEquatable)
{
return Value.Equals((IEquatable)other);
}
else return false;
}
Así que, ¿hay una mejor manera de lidiar con esto, o está definiendo un Discreto Valor DiscreteValue: SignalValue
¿La manera de ir?
Pregunta hecha hace 3 años, 4 meses, 28 días - Por techwizkid
2 Respuestas:
-
Una posible solución a este problema sería modificar la implementación de la interfaz IEquatable en la clase base genérica SignalValue
. En lugar de comparar directamente el valor con el tipo genérico T, podrías solicitar una comparación usando un objeto del tipo IEquatable . Aquí te muestro cómo podrías modificar tu implementación:
csharp public class SignalValue
: ISignalValue { public readonly T Value; public SignalValue(T value) { Value = value; } public string AssociatedSignal { get; set; } public bool Equals(ISignalValue other) { if (other is SignalValue otherSignalValue) { if (Value is IEquatable ) { return ((IEquatable )Value).Equals(otherSignalValue.Value); } else { return false; } } return false; } } En este código, verificamos primero si el objeto other es una instancia de SignalValue
para poder acceder a su Value. Luego, verificamos si el Value de la instancia actual es de tipo IEquatable y realizamos la comparación de igualdad utilizando este tipo. Con esta modificación, puedes definir una clase DiscreteValue como
DiscreteValue : SignalValue<bool>
, lo cual tiene más sentido en términos de la semántica. Y al realizar una comparación de igualdad, puedes utilizar los operadores implícitos como lo tenías en mente, como por ejemplodiscreteValue.Equals(true)
.Espero que esta solución te ayude a mejorar la implementación de la interfaz IEquatable con tipos genéricos en tu código.
Respondida el Dec 19, 2020 a las 19:37 - por Gpt
Votos positivos: 0 | Votos negativos: 0 -
Hay algunas formas de mejorar la implementación de la interfaz
IEquatable<ISignalValue>
para tipos genéricos:Usar restricción de tipo genérico:
En lugar de verificar si
Value
implementaIEquatable<T>
, puedes utilizar una restricción de tipo genérico en la claseSignalValue<T>
para garantizar queT
implementeIEquatable<T>
:public class SignalValue
: ISignalValue where T : IEquatable { // Implementación restante... } Utilizar el tipo base en la interfaz:
Puedes definir la interfaz
IEquatable
para aceptar el tipo baseISignalValue
en lugar de un parámetro genérico:public interface ISignalValue { string AssociatedSignal { get; set; } } public interface IEquatable
where T : ISignalValue { bool Equals(T other); } Implementar
IEquatable<bool>
paraDiscreteValue
:Como
DiscreteValue
representa un valor booleano, puedes implementar directamente la interfazIEquatable<bool>
para ello:public class DiscreteValue : ISignalValue, IEquatable
{ // Implementación restante... public bool Equals(bool other) { return Value == other; } } De esta manera, no es necesario realizar una comprobación de tipo en el método
Equals
deSignalValue<T>
, y la implementación deDiscreteValue
será más eficiente.Ejemplo de uso:
Con las mejoras implementadas, puedes utilizar
DiscreteValue
de la siguiente manera:DiscreteValue dv1 = new DiscreteValue(true); DiscreteValue dv2 = new DiscreteValue(false); Console.WriteLine(dv1.Equals(true)); // True Console.WriteLine(dv1.Equals(dv2)); // False
Estas mejoras simplifican la implementación de la interfaz
IEquatable
para tipos genéricos y hacen que el código sea más eficiente y legible.Respondida el Dec 19, 2020 a las 19:45 - por Gemini
Votos positivos: 0 | Votos negativos: 0