ben*_*wey 13 c# generics reflection
我正在尝试编写一个通用的Parse方法,该方法转换并返回NamedValueCollection中的强类型值.我尝试了两种方法,但这两种方法都通过装箱和拆箱来获得价值.有谁知道避免拳击的方法?如果你在生产中看到这个你会不喜欢它,它的性能有多糟糕?
Usuage:
var id = Request.QueryString.Parse<int>("id");
Run Code Online (Sandbox Code Playgroud)
尝试#1:
public static T Parse<T>(this NameValueCollection col, string key)
{
string value = col[key];
if (string.IsNullOrEmpty(value))
return default(T);
if (typeof(T) == typeof(int))
{
//return int.Parse(value); // cannot convert int to T
//return (T)int.Parse(value); // cannot convert int to T
return (T)(object)int.Parse(value); // works but boxes
}
if (typeof(T) == typeof(long))
{
return (T)(object)long.Parse(value); // works but boxes
}
...
return default(T);
}
Run Code Online (Sandbox Code Playgroud)
尝试#2(使用反射):
public static T Parse<T>(this NameValueCollection col, string key)
{
string value = col[key];
if (string.IsNullOrEmpty(value))
return default(T);
try
{
var parseMethod = typeof(T).GetMethod("Parse", new Type[] { typeof(string) });
if (parseMethod == null)
return default(T);
// still boxing because invoke returns an object
var parsedVal = parseMethod.Invoke(null, new object[] { value });
return (T)parsedVal;
}
// No Proper Parse Method found
catch(AmbiguousMatchException)
{
}
return default(T);
}
Run Code Online (Sandbox Code Playgroud)
Rob*_*rth 34
public static T Parse<T>(this NameValueCollection col, string key)
{
return (T)Convert.ChangeType(col[key], typeof(T));
}
Run Code Online (Sandbox Code Playgroud)
我不完全确定ChangeType框是不是(我想阅读文档会告诉我,但我现在时间紧迫),但至少它摆脱了所有类型检查.虽然拳击开销不是很高,所以我不会太担心它.如果您担心运行时类型的一致性,我会将函数编写为:
public static T Parse<T>(this NameValueCollection col, string key)
{
T value;
try
{
value = (T)Convert.ChangeType(col[key], typeof(T));
}
catch
{
value = default(T);
}
return value;
}
Run Code Online (Sandbox Code Playgroud)
这样,如果由于某种原因无法转换值,函数将不会弹出.这意味着,当然,您必须检查返回的值(无论如何您都必须这样做,因为用户可以编辑查询字符串).
我认为你过度估计拳击/拆箱的影响.解析方法将有更大的开销(字符串解析),使拳击开销相形见绌.此外,所有if语句都会产生更大的影响.反思对所有人产生了最大的影响.
我不希望在生产中看到这种代码,因为有一种更简洁的方法.我遇到的主要问题是需要覆盖所有案例的大量if语句以及有人可以将任何旧类型传递给它的事实.
我要做的是为我想要解析的每个类型编写一个解析函数(即ParseInt()).它更清晰,并且很好地定义了该函数将尝试做什么.此外,对于短静态方法,编译器更可能内联它们,从而保存函数调用.
我认为这是泛型的一个不好的应用,这样做的任何特殊原因?
我将添加一些未记录的方式:
public static T Convert<T>()
{
if (typeof(T) == typeof(int))
{
int a = 5;
T value = __refvalue(__makeref(a), T);
return value;
}
else if (typeof(T) == typeof(long))
{
long a = 6;
T value = __refvalue(__makeref(a), T);
return value;
}
throw new NotImplementedException();
}
Run Code Online (Sandbox Code Playgroud)
关于它们的文档很少,但它们从 C# 4.0 开始工作。例如在这里阅读C# 的隐藏功能?请记住,无证意味着不受支持,等等等等将来无法工作等等等等,如果你使用它们,魔鬼会来找你等等:-)