Given a generic type T in C#, I wonder how to acquire type Q, which is equal to T? for non-nullable T, and T for already nullable T.
The question arose from real code. I want to unify access to parameters passed through query string in my ASP.NET application. And I want to specify a default value of the same type, but ensure null can be passed as a default value.
public static T FetchValue<T>(
string name,
<T? for non-nullable, T otherwise> default_value = null) // How to write this?
{
var page = HttpContext.Current.Handler as Page;
string str = page.Request.QueryString[name];
if (str == null)
{
if (default_value == null)
{
throw new HttpRequestValidationException("A " + name + " must be specified.");
}
else
{
return default_value;
}
}
return (T)Convert.ChangeType(str, typeof(T));
}
Currently I’m forced having two overloads of the FetchValue – one without default value, and one with it:
public static T FetchValue<T>(string name);
public static T FetchValue<T>(string name, T default_value);
It works fine, but I wonder whether it is possible to merge both functions like this.
In C++ I would use type-traits, like PromoteNullable<T>::type with two specializations of PromoteNullable for both nullable and non-nullable types. But what about C#?
Doesn’t directly answer the question as posed, but I’d write this:
So the bulk of the code exists only once – and you can even now actually have the calling code choose to have
nullas a default value, if it so chooses.Even if you could create the parameter declaration you wanted, this line would still be an issue:
If it turned out that
default_valuewas aT?rather than aT, then the above code doesn’t work. Even if you do a cast:there’s still an issue – that to cast from
T?toT, the compiler actually has to insert a call to obtain theValueproperty of the nullable. But that call wouldn’t be valid if the type ofdefault_valuewas justT.In C# Generics, the compiler has to create one piece of IL for the method. There’s no way to insert an optional piece of code that may access
Value.