Entonces tengo esta clase:
public class Foo<T> where T : ???
{
private T item;
public bool IsNull()
{
return item == null;
}
}
Ahora estoy buscando una restricción de tipo que me permita usar todo como parámetro de tipo que pueda ser null
. Eso significa todos los tipos de referencia, así como todos los tipos Nullable
( T?
):
Foo<String> ... = ...
Foo<int?> ... = ...
debería ser posible.
Usar class
como restricción de tipo solo me permite usar los tipos de referencia.
Información adicional:
estoy escribiendo una aplicación de tuberías y filtros, y quiero usar una null
referencia como el último elemento que pasa a la tubería, de modo que cada filtro pueda apagarse bien, hacer limpieza, etc.
IFoo<T>
como tipo de trabajo y crear instancias a través de un método de fábrica? Eso podría funcionar.Respuestas:
Si está dispuesto a realizar una verificación en tiempo de ejecución en el constructor de Foo en lugar de realizar una verificación en tiempo de compilación, puede verificar si el tipo no es una referencia o un tipo anulable, y lanzar una excepción si ese es el caso.
Me doy cuenta de que solo tener una verificación de tiempo de ejecución puede ser inaceptable, pero por si acaso:
Luego, el siguiente código se compila, pero el último (
foo3
) arroja una excepción en el constructor:fuente
static bool isValidType
campo que estableció en el constructor estático, luego simplemente verifique esa marca en el constructor de instancia y arroje si es un tipo no válido para que no esté haciendo todo el trabajo de verificación cada vez que construya una instancia. Utilizo este patrón a menudo.No sé cómo implementar equivalente a OR en genéricos. Sin embargo, puedo proponer usar la palabra clave predeterminada para crear un valor nulo para los tipos que aceptan valores NULL y un valor 0 para las estructuras:
También puede implementar su versión de Nullable:
Ejemplo:
fuente
Me encontré con este problema por un caso más simple de querer un método estático genérico que pudiera tomar cualquier cosa "anulable" (ya sea tipos de referencia o Nullables), lo que me llevó a esta pregunta sin una solución satisfactoria. Así que se me ocurrió mi propia solución, que era relativamente más fácil de resolver que la pregunta indicada por el OP al tener simplemente dos métodos sobrecargados, uno que toma un
T
y tiene la restricciónwhere T : class
y otro que toma unT?
tienewhere T : struct
.Luego me di cuenta de que esa solución también se puede aplicar a este problema para crear una solución que se pueda verificar en tiempo de compilación haciendo que el constructor sea privado (o protegido) y utilizando un método de fábrica estático:
Ahora podemos usarlo así:
Si desea un constructor sin parámetros, no obtendrá la delicadeza de la sobrecarga, pero aún puede hacer algo como esto:
Y utilícelo así:
Hay algunas desventajas en esta solución, una es que puede preferir usar 'nuevo' para construir objetos. Otra es que usted no será capaz de utilizar
Foo<T>
como un argumento de tipo genérico para una restricción tipo de algo como:where TFoo: new()
. Por último, está el código extra que necesita aquí, que aumentaría especialmente si necesita varios constructores sobrecargados.fuente
Como se mencionó, no puede tener una verificación en tiempo de compilación. Las restricciones genéricas en .NET son muy deficientes y no son compatibles con la mayoría de los escenarios.
Sin embargo, considero que esta es una mejor solución para la verificación del tiempo de ejecución. Se puede optimizar en tiempo de compilación JIT, ya que ambas son constantes.
fuente
Tal restricción de tipo no es posible. Según la documentación de las restricciones de tipo, no existe ninguna restricción que capture tanto los tipos que aceptan valores NULL como los de referencia. Dado que las restricciones solo se pueden combinar en una conjunción, no hay forma de crear tal restricción por combinación.
Sin embargo, para sus necesidades, puede recurrir a un parámetro de tipo sin restricción, ya que siempre puede verificar == null. Si el tipo es un tipo de valor, la comprobación siempre se evaluará como falsa. Entonces posiblemente obtendrá la advertencia de R # "Posible comparación del tipo de valor con nulo", que no es crítica, siempre que la semántica sea la adecuada para usted.
Una alternativa podría ser utilizar
en lugar de la comprobación nula, ya que por defecto (T) donde T: clase siempre es nula. Esto, sin embargo, significa que no puede distinguir si un valor que no acepta valores NULL nunca se ha establecido explícitamente o simplemente se estableció en su valor predeterminado.
fuente
yo suelo
fuente
fuente