简体   繁体   English

通用TryParse扩展方法

[英]Generic TryParse Extension method

Code taken from here 代码来自这里

I would like to hear some expert opinions on this extension method. 我想听听一些关于这种扩展方法的专家意见。 I do plan to use it, but would like to hear about any known problems i may face. 我打算使用它,但想知道我可能遇到的任何已知问题。

Am i better of using on primative types TryParse methods? 我更喜欢在主要类型上使用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;
        }

The TryParse pattern is best following the standard pattern, which allows use with non-structs, too: 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;
    }
}

Note I've accepted a string here, because that is what me most commonly mean by TryParse ; 注意我在这里接受了一个string ,因为这是我最常用的TryParse意思; otherwise, Convert.ChangeType might be more appropriate. 否则, Convert.ChangeType可能更合适。

I see no reason for this to be an extension method (as per this in the question's example), and certainly it is inadvisable to pollute object with too many extension methods. 我看不出有任何理由这是一个扩展方法(按照this在问题的例子), 肯定是不可取的污染object有太多的扩展方法。

The extensions below might be useful to you. 下面的扩展可能对您有用。 They work on any type that has a Parse or TryParse method... 它们适用于任何具有Parse或TryParse方法的类型......

They come from my Extensions library here: http://www.codeproject.com/KB/dotnet/MBGExtensionsLibrary.aspx 它们来自我的扩展库: http//www.codeproject.com/KB/dotnet/MBGExtensionsLibrary.aspx

Although that project is probably a bit out-of-date...I'll have to update it as some point :-D 虽然那个项目可能有点过时了......但我必须将其更新为:•D

Hope this helps! 希望这可以帮助!

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;
        }
    }

For simpler code, you can do this: 对于更简单的代码,您可以这样做:

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

Credit to Thomas Levesque at https://stackoverflow.com/a/1465930/24315 . 感谢Thomas Levesque, 网址https://stackoverflow.com/a/1465930/24315

Generics are most useful when you want to vary the public contract of a method or class, and the internals of the method or class don't really care (or care much) about the type that varies. 当你想要改变一个方法或类的公共契约时,泛型是最有用的,并且方法或类的内部并不真正关心(或关心)变化的类型。

Some examples: 一些例子:

List<T> is a collection you can put things in, and internally the class doesn't care (much) about what that type is. List<T>是一个可以放入内容的集合,在内部,类不关心(很多)该类型是什么。

T System.Linq.Enumerable.First<T>(IEnumerable<T> source) returns the first element out of a bunch of elements. T System.Linq.Enumerable.First<T>(IEnumerable<T> source)返回一堆元素中的第一个元素。 This method doesn't need to know internally what type that is in order to get the job done. 此方法不需要在内部知道什么类型才能完成工作。

By contrast, a parsing method must change its behavior based on the type of the result. 相反,解析方法必须根据结果的类型更改其行为。 In the supplied method, there is Strategy which pushes the behaviors out to other methods, but there is a runtime cost for that choice. 在提供的方法中,有一个策略将行为推送到其他方法,但是该选择存在运行时成本。

The alternative is to let the caller (who must know the Type or they couldn't call the generic method with it), pick the converter. 另一种方法是让调用者(他们必须知道Type或他们不能用它调用泛型方法),选择转换器。 This choice is able to be made at design time or compile time and so incurs 0 runtime cost. 这种选择可以在设计时或编译时进行,因此会产生0运行时成本。

Side Note: Please don't use the re-throw everything idiom. 旁注:请不要使用重新抛出一切成语。 All it does is reset the call stack and you don't ever want to do that. 它只是重置调用堆栈,你不想这样做。

catch (Exception ex)
{
  throw ex;
}

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM