Mik*_*ail 8 c# generics nullable metaprogramming type-traits
给定TC#中的泛型类型,我想知道如何获取类型Q,它等于T?非可空类型T,并且T已经可以为空T.
问题来自真实的代码.我想统一访问我的ASP.NET应用程序中通过查询字符串传递的参数.我想指定相同类型的默认值,但确保null可以作为默认值传递.
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));
}
Run Code Online (Sandbox Code Playgroud)
目前我被迫有两个重载FetchValue- 一个没有默认值,一个有它:
public static T FetchValue<T>(string name);
public static T FetchValue<T>(string name, T default_value);
Run Code Online (Sandbox Code Playgroud)
它运行正常,但我想知道是否可以合并这两个函数.
在C++中,我会用类型特征,喜欢PromoteNullable<T>::type用两个专业PromoteNullable的都为空的和非可空类型.但是C#怎么样?
没有直接回答所提出的问题,但我会这样写:
public static T FetchValue<T>(string name)
{
T value;
if (TryFetchValue(name, out value))
return value;
throw new HttpRequestValidationException("A " + name + " must be specified.");
}
public static T FetchValue<T>(string name, T default_value)
{
T value;
if (TryFetchValue(name, out value))
return value;
return default_value;
}
private static bool TryFetchValue<T>(
string name,
out T value)
{
var page = HttpContext.Current.Handler as Page;
string str = page.Request.QueryString[name];
if (str == null)
{
value = default(T);
return false;
}
value = (T)Convert.ChangeType(str, typeof(T));
return true;
}
Run Code Online (Sandbox Code Playgroud)
因此,大部分代码只存在一次 - 即使现在您实际上也可以让调用代码选择将其作为null默认值(如果它选择的话)。
即使您可以创建所需的参数声明,这一行仍然是一个问题:
return default_value;
Run Code Online (Sandbox Code Playgroud)
如果结果default_value是 aT?而不是 a T,那么上面的代码就不起作用。即使你做了演员:
return (T)default_value;
Run Code Online (Sandbox Code Playgroud)
仍然存在一个问题 - 要从T?to转换T,编译器实际上必须插入一个调用来获取可Value为空的属性。default_value但如果 的类型只是,那么该调用将无效T。
在 C# 泛型中,编译器必须为方法创建一段 IL。无法插入可以访问Value.