Tengo un par de métodos que he escrito en mi biblioteca de utilidades en los que he confiado mucho. El primero es un método que convierte cualquier tipo a su forma Nullable <Type> correspondiente:
public static Type GetNullableType(Type TypeToConvert)
{
if (TypeToConvert == null)
return null;
if (IsTypeNullable(TypeToConvert))
return TypeToConvert;
if (TypeToConvert.IsValueType && TypeToConvert != typeof(void))
return typeof(Nullable<>).MakeGenericType(TypeToConvert);
return null;
}
El segundo método simplemente informa si un tipo determinado es anulable. Este método es llamado por el primero y es útil por separado:
public static bool IsTypeNullable(Type TypeToTest)
{
if (TypeToTest == null)
return false;
if (!TypeToTest.IsValueType)
return true;
return TypeToTest.IsGenericType && TypeToTest.GetGenericTypeDefinition() == typeof(Nullable<>);
}
La implementación IsTypeNullable anterior funciona como un campeón cada vez, pero es un poco detallada y lenta en su última línea de código. El siguiente cuerpo de código es el mismo que el anterior para IsTypeNullable, excepto que la última línea de código es más simple y rápida:
if (TypeToTest == null)
return false;
if (!TypeToTest.IsValueType)
return true;
return Nullable.GetUnderlyingType(TypeToTest) != null;
¡Disfrutar!
marca
PD: Acerca de la "nulabilidad"
Debo repetir una declaración sobre la nulabilidad que hice en una publicación separada, que se aplica directamente para abordar correctamente este tema. Es decir, creo que el enfoque de la discusión aquí no debería ser cómo verificar si un objeto es un tipo genérico que acepta valores NULL, sino más bien si se puede asignar un valor nulo a un objeto de su tipo. En otras palabras, creo que deberíamos estar determinando si un tipo de objeto es anulable, no si es anulable. La diferencia está en la semántica, a saber, las razones prácticas para determinar la nulabilidad, que suele ser todo lo que importa.
En un sistema que usa objetos con tipos posiblemente desconocidos hasta el momento de la ejecución (servicios web, llamadas remotas, bases de datos, feeds, etc.), un requisito común es determinar si se puede asignar un nulo al objeto o si el objeto puede contener un nulo. La realización de tales operaciones en tipos que no aceptan valores NULL probablemente producirá errores, generalmente excepciones, que son muy costosos tanto en términos de rendimiento como de requisitos de codificación. Para adoptar el enfoque altamente preferido de evitar proactivamente tales problemas, es necesario determinar si un objeto de un Tipo arbitrario es capaz de contener un nulo; es decir, si es generalmente "anulable".
En un sentido muy práctico y típico, la nulabilidad en términos de .NET no implica necesariamente que el tipo de un objeto sea una forma de Nullable. De hecho, en muchos casos, los objetos tienen tipos de referencia, pueden contener un valor nulo y, por lo tanto, son todos anulables; ninguno de estos tiene un tipo que acepta valores NULL. Por lo tanto, para fines prácticos en la mayoría de los escenarios, las pruebas deben realizarse para el concepto general de nulabilidad, frente al concepto dependiente de la implementación de Nullable. Por lo tanto, no deberíamos quedarnos colgados concentrándonos únicamente en el tipo .NET que admite valores nulos, sino que deberíamos incorporar nuestra comprensión de sus requisitos y comportamiento en el proceso de enfocarnos en el concepto general y práctico de nulabilidad.