La restricción struct
en Nullable<T>
es en mi humilde opinión realmente desafortunado. Algo como un Nullable<String>
o un Nullable<Nullable<Nullable<int>>>
puede ser un desperdicio, pero ¿y qué? Box el primero como su contenido; desempaquetarlo como contenido y establecer HasValue
si el contenido no es nulo. Escriba el primero como int
si todos los elementos nulos informan HasValue
, y cuando desempaquete, establezca HasValue
de todos los elementos anidados si el contenido no fue nulo.
De lo contrario, le sugiero que cree una clase genérica estática con el parámetro de tipo T
que contiene una propiedad de delegado que acepta un T
como parámetro. La propiedad debe devolver el contenido de un campo privado que debe inicializarse para apuntar a un método que verificará el tipo de T
y establecerá el delegado en la versión struct
o class
, según corresponda.
Aquí hay una muestra de lo que estoy hablando; éste usa varias restricciones de interfaz en lugar de restricciones de estructura/clase, pero los mismos principios se pueden usar con la misma eficacia.
static class _FooDispatcher<T>
{
public static Action<T> Foo = setupFoo;
static void doFooWithIGoodFoo<TT>(TT param) where TT : IGoodFoo
{
Console.WriteLine("Dispatching as IGoodFoo with {1} type {0}", typeof(TT).ToString(), typeof(TT).IsValueType ? "value" : "reference");
param.Foo();
}
static void doFooWithIOkayFoo<TT>(TT param) where TT : IOkayFoo
{
Console.WriteLine("Dispatching as IOkayFoo with {1} type {0}", typeof(TT).ToString(), typeof(TT).IsValueType ? "value" : "reference");
param.Foo();
}
static void doFooSomehow<TT>(TT param)
{
Console.WriteLine("Nothing exciting with {1} type {0}", typeof(TT).ToString(), typeof(TT).IsValueType ? "value" : "reference");
}
static void setupFoo(T param)
{
System.Reflection.MethodInfo mi;
if (typeof(IGoodFoo).IsAssignableFrom(typeof(T)))
mi = typeof(_FooDispatcher<T>).GetMethod("doFooWithIGoodFoo", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
else if (typeof(IOkayFoo).IsAssignableFrom(typeof(T)))
mi = typeof(_FooDispatcher<T>).GetMethod("doFooWithIOkayFoo", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
else
mi = typeof(_FooDispatcher<T>).GetMethod("doFooSomehow", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
Foo = (Action<T>)(@Delegate.CreateDelegate(typeof(Action<T>), mi.MakeGenericMethod(typeof(T))));
Foo(param);
}
}
Fuera de interés, ¿qué tipo de cosas intentaba hacer su caso de uso real? – AakashM
@AakashM: simple, necesitaba convertir tipos que aceptan nulos de una manera diferente a los tipos de valores que no admiten nulos. Pensé que una sobrecarga genérica era una manera rápida de solucionarlo. El método toma un objeto y un tipo param y no puedo restringir el tipo param (bueno, puedo, pero no puedo sobrecargarlo). – Abel