Подтвердить что ты не робот

Общий метод расширения TryParse

Код, взятый из здесь

Я хотел бы услышать мнение экспертов по этому методу расширения. Я планирую использовать его, но хотел бы услышать о любых известных проблемах, с которыми я могу столкнуться.

Мне лучше использовать на примитивных типах методы 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;
        }
4b9b3361

Ответ 1

Образец 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 слишком многими методами расширения.

Ответ 2

Расширения ниже могут быть полезны для вас. Они работают с любым типом, который имеет метод 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;
        }
    }

Ответ 3

Обобщения наиболее полезны, если вы хотите изменить публичный контракт метода или класса, а внутренности метода или класса действительно не заботятся (или не заботятся) о типе, который изменяется.

Некоторые примеры:

List<T> - это коллекция, в которую вы можете поместить вещи, и внутри класса класс не заботится (много) о том, что это за тип.

T System.Linq.Enumerable.First<T>(IEnumerable<T> source) возвращает первый элемент из группы элементов. Этот метод не обязательно должен знать, какой тип будет выполнен, чтобы выполнить работу.

Напротив, метод синтаксического анализа должен изменить свое поведение в зависимости от типа результата. В поставляемом методе существует Стратегия, которая вытесняет поведение других методов, но для этого выбора существует время выполнения.

Альтернативой является позволить вызывающему абоненту (который должен знать тип или не может вызвать общий метод с ним), выберите конвертер. Этот выбор можно сделать во время разработки или времени компиляции и, следовательно, берет на себя 0 времени исполнения.

Боковое примечание: Пожалуйста, не используйте повторный бросок всей идиомы. Все, что он делает, это reset стек вызовов, и вы никогда не хотите этого делать.

catch (Exception ex)
{
  throw ex;
}

Ответ 4

Для более простого кода вы можете сделать это:

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

Кредит Томасу Левеске в fooobar.com/questions/423348/....

Ответ 5

Он использует отражение и, следовательно, может быть медленным, если производительность является проблемой.