代码来自here
我想听听有关此扩展方法的一些专家意见。我打算使用它,但想知道我可能遇到的任何已知问题。
我最好在初级类型上使用TryParse方法吗?
public static T? TryParse<T>(this object obj) where T : struct
{
if (obj == null) return null;
T? result = null;
TypeConverter converter = TypeDescriptor.GetConverter(typeof(T));
if (converter != null)
{
try
{
string str = obj.ToString();
result = (T)converter.ConvertFromString(str);
}
catch (Exception ex)
{
throw ex;
}
}
return result;
}
答案 0 :(得分:25)
TryParse
模式最好遵循标准模式,允许与非结构一起使用:
public static bool TryParse<T>(string s, out T value) {
TypeConverter converter = TypeDescriptor.GetConverter(typeof(T));
try {
value = (T) converter.ConvertFromString(s);
return true;
} catch {
value = default(T);
return false;
}
}
注意我在这里接受了string
,因为这是TryParse
最常见的意思;否则,Convert.ChangeType
可能更合适。
我认为没有理由将其作为扩展方法(根据问题示例中的this
),当然不宜过多地污染object
扩展方法。
答案 1 :(得分:4)
以下扩展程序可能对您有用。它们适用于任何具有Parse或TryParse方法的类型......
他们来自我的扩展程序库: http://www.codeproject.com/KB/dotnet/MBGExtensionsLibrary.aspx
虽然这个项目可能有点过时了......我必须更新它作为某些观点:-D
希望这有帮助!
public static class StringExtensions
{
public static TOut ParseOrDefault<TOut>(this string input)
{
return input.ParseOrDefault(default(TOut));
}
public static TOut ParseOrDefault<TOut>(this string input, TOut defaultValue)
{
Type type = typeof(TOut);
MethodInfo parseMethod = type.GetMethod("Parse", new Type[] { typeof(string) });
if (parseMethod != null)
{
var value = parseMethod.Invoke(null, new string[] { input });
return (value is TOut ? (TOut)value : defaultValue);
}
else { return defaultValue; }
}
public static bool TryParseOrDefault<TOut>(this string input, out TOut output)
{
return input.TryParseOrDefault(out output, default(TOut));
}
public static bool TryParseOrDefault<TOut>(this string input, out TOut output, TOut defaultValue)
{
output = defaultValue;
Type type = typeof(TOut);
MethodInfo parseMethod = type.GetMethod(
"TryParse",
new Type[] { typeof(string), typeof(TOut).MakeByRefType() });
if (parseMethod != null)
{
object[] parameters = new object[] { input, output };
var value = parseMethod.Invoke(null, parameters);
if (value is bool)
{
bool successful = (bool)value;
if (successful)
{
output = (TOut)parameters[1];
return true;
}
}
}
return false;
}
}
答案 2 :(得分:3)
当您想要改变方法或类的公共合同时,泛型是最有用的,并且方法或类的内部并不真正关心(或关心)变化的类型。
一些例子:
List<T>
是一个可以放入内容的集合,而且内部的类并不关心(很多)该类型的内容。
T System.Linq.Enumerable.First<T>(IEnumerable<T> source)
返回一堆元素中的第一个元素。这种方法不需要在内部知道什么类型才能完成工作。
相比之下,解析方法必须根据结果的类型更改其行为。在提供的方法中,有策略将行为推送到其他方法,但是该选择存在运行时成本。
另一种方法是让调用者(必须知道Type或他们不能用它调用泛型方法),选择转换器。这种选择可以在设计时或编译时进行,因此会产生0运行时成本。
旁注:请不要使用重新抛出一切成语。它只是重置调用堆栈,你不想这样做。
catch (Exception ex)
{
throw ex;
}
答案 3 :(得分:3)
对于更简单的代码,您可以这样做:
T value = (T)Convert.ChangeType(value, typeof(T));
在https://stackoverflow.com/a/1465930/24315感谢Thomas Levesque。
答案 4 :(得分:1)
如果性能有问题,它会使用反射,因此可能会很慢。