通用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
返回一堆元素中的第一个元素。 此方法不需要在内部知道什么类型才能完成工作。
相反,解析方法必须根据结果的类型更改其行为。 在提供的方法中,有一个策略将行为推送到其他方法,但是该选择存在运行时成本。
另一种方法是让调用者(他们必须知道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,因此可能很慢。