tutorial - interfaces generics c#
Restricción genérica para hacer coincidir los tipos numéricos (6)
Esta pregunta ya tiene una respuesta aquí:
Intento escribir un método de extensión en tipos numéricos para usarlo en un marco de prueba fluido que estoy construyendo. Básicamente, quiero hacer esto:
public static ShouldBeGreaterThan<T>(this T actual, T expected, string message)
where T : int || T: double || etc...
Justo where T : struct
no funciona, ya que también coincidirá con string
y bool
, y posiblemente con algo más que estoy olvidando. ¿Hay algo que pueda hacer para hacer coincidir solo los tipos numéricos? (Específicamente, los tipos que implementan los operadores >
y <
, para que pueda compararlos ... si esto significa que también estoy haciendo coincidir fechas, en realidad no importa; la extensión seguirá haciendo lo que espero).
En este caso, desea restringir su interfaz genérica a IComparable
, que le da acceso al método CompareTo
, ya que esta interfaz le permite responder la pregunta ShouldBeGreaterThan
.
Los tipos numéricos implementarán esa interfaz y el hecho de que también funcione en cadenas no debería molestarte demasiado.
Es difícil limitarlo solo a los números, ya que no hay nada común como INumeric
para usar como filtro. De hecho, sospecho que el enfoque más fácil aquí es no insistir en la restricción y usar Comparer<T>.Default.Compare
dentro del método.
Este tipo incorporado admite el IComparable<T>
genérico y el IComparable
no genérico, y admite ref-types, value-types y uso elevado mediante Nullable<T>
.
Para un uso total del operador , consulte la clase Operator
de MiscUtil y GreaterThan
, etc., que puede ser útil si realmente desea utilizar el operador (en lugar de la interfaz). También proporciona acceso a otros operadores como Add
etc.
Esta solución alternativa puede ser útil: Solución mediante políticas . Proporciona seguridad de tiempo de compilación.
está plagado de este tipo de preguntas. Eche un vistazo a esta búsqueda . C # no admite una forma de definir un tipo genérico restringido por números. Tristemente, su mejor opción es implementar el método de extensión en todos los objetos y hacer un cambio basado en el tipo o para crear un conjunto de métodos para ints, dobles, flotantes, etc.
public static bool IsGreaterThan<T>(this T actual, T comp) where T : IComparable<T>
{
return actual.CompareTo(comp) > 0;
}
Puede agregar la restricción struct si así lo desea.
where T : struct,
IComparable,
IComparable<T>,
IConvertible,
IEquatable<T>,
IFormattable
Eso es lo más cerca que puedo llegar a una restricción numérica. Todos los tipos numéricos implementan estas 5 interfaces, pero IFormattable no está implementado por bool, y las cadenas son un tipo de referencia, por lo que no son aplicables.
Hay otras cosas que implementan esto: DateTime, por ejemplo, por lo que no es realmente necesario, pero evita muchas instancias que no desea.