通用TryParse扩展方法

代码取自这里

我想听听一些关于这种扩展方法的专家意见。 我打算使用它,但想知道我可能遇到的任何已知问题。

我更喜欢在主要类型上使用TryParse方法吗?

public static T? TryParse(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; } 

TryParse模式最好遵循标准模式,它也允许使用非结构模式:

 public static bool TryParse(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可能更合适。

我认为没有理由将其作为扩展方法(在问题的例子中如此), 当然 ,使用过多的扩展方法污染object是不可取的。

下面的扩展可能对您有用。 它们适用于任何具有Parse或TryParse方法的类型……

它们来自我的扩展库: http : //www.codeproject.com/KB/dotnet/MBGExtensionsLibrary.aspx

虽然那个项目可能有点过时了……但我必须将其更新为:•D

希望这可以帮助!

 public static class StringExtensions { public static TOut ParseOrDefault(this string input) { return input.ParseOrDefault(default(TOut)); } public static TOut ParseOrDefault(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(this string input, out TOut output) { return input.TryParseOrDefault(out output, default(TOut)); } public static bool TryParseOrDefault(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; } } 

当您想要改变方法或类的公共契约时,generics是最有用的,并且方法或类的内部并不真正关心(或关心)变化的类型。

一些例子:

List是一个可以放入内容的集合,在内部,类不关心(多)关于该类型的内容。

T System.Linq.Enumerable.First(IEnumerable source)返回一堆元素中的第一个元素。 此方法不需要在内部知道什么类型才能完成工作。

相反,解析方法必须根据结果的类型更改其行为。 在提供的方法中,有一个策略将行为推送到其他方法,但是该选择存在运行时成本。

另一种方法是让调用者(他们必须知道Type或他们不能用它调用generics方法),选择转换器。 这种选择可以在设计时或编译时进行,因此会产生0运行时成本。

旁注:请不要使用重新抛出一切成语。 它只是重置调用堆栈,你不想这样做。

 catch (Exception ex) { throw ex; } 

对于更简单的代码,您可以这样做:

 T value = (T)Convert.ChangeType(value, typeof(T)); 

感谢Thomas Levesque, url为https://stackoverflow.com/a/1465930/24315 。

如果性能是一个问题,它使用reflection,因此可能很慢。