Чи існує якась загальна функція Parse (), яка перетворює рядок на будь-який тип за допомогою parse?


91

Я хочу , щоб перетворити рядок загального типу , як intабо dateабо longна підставі загального типу, що повертається значення .

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

Наприклад, якщо передано int, функція повинна виконувати int.parseвнутрішньо.

Відповіді:


132

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>();

класно, але дивна річ його називають ChangeType, тому я міг би подумати, що ця функція виконує якусь роль, а не аналізує
Карім,

7
MSDN каже, що це просто обгортка, яка знаходить правильний метод перетворення вихідного об'єкта, вимагаючи, щоб він реалізував інтерфейс IConvertible.
Ані,

Якщо це потрібно реалізувати, IConvertableчи не слід також обмежувати T, тобто T ChangeType<T>(this object obj) where T : IConvertable?
Ліам

2
@Liam: Ні, це objповинно бути IConvertible, але це неможливо вказати під час компіляції.
Ані

якщо мені потрібно щось на зразок TryChangeType, що повертає значення null або false у випадку відмови? Тільки ловлячи виняток?
Безнадійний

21

Ну, схоже, я запізнився відповідати на цю тему. Але ось моя реалізація:

По суті, я створив метод Extention для класу 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;
           }

ІМХО це краща відповідь, оскільки воно також містить "обнулюваний" аспект
Оле Альберс,

чи існує конкретна причина, за якою ви використовуєте TypeDescriptorдля типів, що дозволяють обнуляти, і Convert.ChangeTypeдля типів, що не мають дозволу? Весь цей tryблок можна зменшити лише до TypeConverter2-х рядків коду, і він буде працювати як для нульового, так і для ненульованого.
IMujagic


8

чистіша версія відповіді Пране

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

0

У .NET існує кілька домовленостей щодо перетворення об’єктів одного типу в інший.

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

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

Він також повертається до способів, про які я згадав вище, якщо тип не має відповідного методу синтаксичного аналізу (Див. Розділ продуктивності в readme).

var v = new ValueString("15"); // struct
var i = v.As<int>(); // Calls int.Parse.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.