Есть ли какая-либо общая функция Parse(), которая преобразует строку в любой тип с помощью синтаксического анализа?

Я хочу преобразовать строку в универсальный тип, такой как int или date или long, на основе универсального возвращаемого типа.

В основном это функция типа Parse<T>(String), которая возвращает элемент типа T.

Например, если было передано целое число, функция должна выполнить int.parse внутри.


person Karim    schedule 17.08.2010    source источник


Ответы (5)


System.Convert.ChangeType

В соответствии с вашим примером вы можете сделать:

int i = (int)Convert.ChangeType("123", typeof(int));
DateTime dt = (DateTime)Convert.ChangeType("2009/12/12", typeof(DateTime));

Чтобы удовлетворить ваше требование «общий тип возвращаемого значения», вы можете написать свой собственный метод расширения:

public static T ChangeType<T>(this object obj)
{
    return (T)Convert.ChangeType(obj, typeof(T));
}

Это позволит вам сделать:

int i = "123".ChangeType<int>();
person Ani    schedule 17.08.2010
comment
круто, но странно, что она называется ChangeType, поэтому я подумал, что эта функция выполняет какое-то приведение, а не анализирует - person Karim; 17.08.2010
comment
MSDN говорит, что это просто оболочка, которая находит правильный метод преобразования исходного объекта, требуя, чтобы он реализовал интерфейс IConvertible. - person Ani; 17.08.2010
comment
Если необходимо реализовать IConvertable, не должны ли вы также ограничивать T, то есть T ChangeType<T>(this object obj) where T : IConvertable? - person Liam; 30.07.2015
comment
@Liam: Нет, это obj должно быть IConvertible, но нет возможности указать это во время компиляции. - person Ani; 30.07.2015
comment
если мне нужно что-то вроде TryChangeType, которое возвращает null или false в случае сбоя? Только перехватив исключение? - person Hopeless; 15.10.2015
comment
Я делаю именно это в своем коде... Проблема в том, что 1 не будет преобразовано в логическое значение. Есть ли общий способ обработки всех типов значений - person Luke T O'Brien; 12.03.2019

Что ж, похоже, я слишком поздно отвечаю в этой теме. Но вот моя реализация:

По сути, я создал метод расширения для класса Object. Он обрабатывает все типы, то есть обнуляемые, классы и структуры.

 public static T ConvertTo<T>(this object value)
           {
               T returnValue;

               if (value is T variable)
                   returnValue = variable;
               else
                   try
                   {
                       //Handling Nullable types i.e, int?, double?, bool? .. etc
                       if (Nullable.GetUnderlyingType(typeof(T)) != null)
                       {
                           TypeConverter conv = TypeDescriptor.GetConverter(typeof(T));
                           returnValue = (T) conv.ConvertFrom(value);
                       }
                       else
                       {
                           returnValue = (T) Convert.ChangeType(value, typeof(T));
                       }
                   }
                   catch (Exception)
                   {
                       returnValue = default(T);
                   }

               return returnValue;
           }
person Pranay Deep    schedule 03.04.2018
comment
ИМХО, это лучший ответ, потому что он также содержит нулевой аспект - person Ole Albers; 11.04.2018
comment
есть ли конкретная причина, по которой вы используете TypeDescriptor для типов, допускающих значение NULL, и Convert.ChangeType для типов, не допускающих значения NULL? Весь этот try блок можно сократить только до TypeConverter 2 строк кода, и он будет работать как для nullable, так и для non-nullable. - person IMujagic; 17.01.2020

более чистая версия ответа Праная

public static T ConvertTo<T>(this object value)
{
    if (value is T variable) return variable;

    try
    {
        //Handling Nullable types i.e, int?, double?, bool? .. etc
        if (Nullable.GetUnderlyingType(typeof(T)) != null)
        {
            return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFrom(value);
        }

        return (T)Convert.ChangeType(value, typeof(T));
    }
    catch (Exception)
    {
        return default(T);
    }
}
person Eonasdan    schedule 19.07.2018

System.Convert.ChangeType не преобразуется ни в какой тип. Подумайте о следующем:

  • типы, допускающие значение null
  • перечисления
  • Гайд и др.

Эти преобразования возможны с помощью эта реализация ChangeType.

person Alex Siepman    schedule 15.04.2012

В .NET есть несколько соглашений для преобразования объектов одного типа в другой.

Но эти методы намного медленнее, чем ваш типичный T.Parse(string), вызывают коробку и требуют большого количества аллокаций каждый раз, когда вы хотите преобразовать одно значение.

Для ValueString я решил найти подходящий статический метод анализа типа с использованием отражения, построить лямбда-выражение, вызывающее его, и кэширует скомпилированный делегат для использования в будущем (см. этот ответ для примера).

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

var v = new ValueString("15"); // struct
var i = v.As<int>(); // Calls int.Parse.
person Şafak Gür    schedule 17.11.2017