I have an interesting problem. I'd like to create a generic class that can deal with both Reference types as well as Nullable<T> types. Basically I want something like:
public class ClassWithNull<T>
{
public T varName = null;
}
Now this, of course, does not compile because not all types can be assigned null, namely non-nullable value types. But the problem is Nullable<T> is a value type, so simply adding where T : class doesn't help me. My generics-foo is not too strong, but I haven't been able to find any way to say that T must either be a reference type or a nullable value type.
The idea I have to solve this is to make ClassWithNull<T> an abstract class. I could then add two sub-classes, one to deal with reference types and one to deal with nullable value types. Then, a static factory method in the base class could use reflection to determine which sub-class ought to be constructed. Something like:
public static ClassWithNull<T> CreateClassWithNull<T>()
{
StackTrace st = new StackTrace();
Type type = st.GetFrame(1).GetMethod().GetGenericArguments()[0];
if (!type.IsValueType)
{
return new ClassWithReferenceType<T>();
}
else if (type == typeof(Nullable))
{
return new ClassWithNullableValueType<T>();
}
else
{
throw new Exception("Must provide nullable type.");
}
}
The problem here is that generics are resolved statically. If ClassWithReferenceType<U> expects U to be a reference type, then calling new ClassWithReferenceType<T>() in the factory method is a compilation error since T is not required to be a reference type. The compiler does not know about the run time check.
Any ideas about how to implement such a thing?
How about:
public class ClassWithNull<T>
{
public T varName = default(T);
}
(Actually, you don't even need the assignment - you can just leave it to be the default value on construction. But you might want default(T) for local variables.)
That won't stop you from using it incorrectly with a non-nullable value type - but is that enough?
If that doesn't help you, I would suggest writing two static methods, like this:
public static ClassWithNull<T> CreateClassWithNullForClass<T> where T : class
{
return new ClassWithReferenceType<T>();
}
public static ClassWithNull<T> CreateClassWithNullForNullable<T> where T : struct
{
return new ClassWithNullableValueType<T>();
}
The field in ClassWithNullableValueType would be Nullable<T> - T would be the underlying type.
Now if you want overloads of the same method, that gets a little harder, particularly if you don't want to pass any parameters. It's possible, but really, really horrible.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With