Я хочу преобразовать строку в универсальный тип, например int
или date
или long
на основе универсального возвращаемого типа.
По сути, такая функция Parse<T>(String)
возвращает элемент типа T
.
Например, если было передано int, функция должна работать int.parse
внутри.
c#
string
parsing
type-conversion
Карим
источник
источник
IConvertable
не следует ли вам также ограничиватьT
, т.е.T ChangeType<T>(this object obj) where T : IConvertable
?obj
должно быть такIConvertible
, но нет возможности указать это во время компиляции.Похоже, я слишком поздно отвечать в этой теме. Но вот моя реализация:
По сути, я создал метод расширения для класса 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
типы, допускающие значение NULL, и типы,Convert.ChangeType
не допускающие значения NULL? Весь этотtry
блок можно сократить только доTypeConverter
2 строк кода, и он будет работать как для обнуляемых, так и для непустых.System.Convert.ChangeType
не преобразуется ни в один тип. Подумайте о следующем:Эти преобразования возможны с этой реализацией ChangeType .
источник
более чистая версия ответа Праная
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); } }
источник
В .NET существует несколько соглашений для преобразования объектов одного типа в другой.
Но эти методы намного медленнее, чем ваши обычные
T.Parse(string)
, вызывают упаковку и требуют большого количества выделений каждый раз, когда вы хотите преобразовать одно значение.Для ValueString я решил найти подходящий метод статического анализа типа с использованием отражения, построить вызывающее его лямбда-выражение и кэшировать скомпилированный делегат для будущего использования (см. Этот ответ для примера).
Он также использует способы, упомянутые выше, если у типа нет подходящего метода синтаксического анализа (см. Раздел о производительности в файле readme).
var v = new ValueString("15"); // struct var i = v.As<int>(); // Calls int.Parse.
источник