Чи існує якась загальна функція 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.