TypeConverter не может конвертировать из некоторых базовых типов в те же базовые типы
Почему те возвращают true
:
TypeDescriptor.GetConverter(typeof(double)).CanConvertTo(typeof(double));
TypeDescriptor.GetConverter(typeof(int)).CanConvertTo(typeof(int));
когда те возвращают false
?
TypeDescriptor.GetConverter(typeof(decimal)).CanConvertTo(typeof(decimal));
TypeDescriptor.GetConverter(typeof(bool)).CanConvertTo(typeof(bool));
Событие, считающее, что все конвертеры, возвращаемые GetConverter, должны только преобразовывать типы в строку и из нее:
Я использую .NET Framework 4.5.2.
Ответы
Ответ 1
DecimalConverter
(а также DoubleConverter
и Int32Converter
) переопределяет CanConvertTo
, чтобы указать, что он может преобразовать в строки (из-за того, что делает base.CanConvertTo
), и всех примитивных типов CLR. Из Справочный источник:
public override bool CanConvertTo(ITypeDescriptorContext context, Type t)
{
if (base.CanConvertTo(context, t) || t.IsPrimitive) {
return true;
}
return false;
}
decimal
НЕ является примитивным типом с точки зрения CLR, поэтому преобразователь возвращает false
при передаче typeof(decimal)
.
BooleanConverter
не переопределяет CanConvertTo
, поэтому он попадает в базовую реализацию, которая допускает только преобразование в string
:
public virtual bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return (destinationType == typeof(string));
}
Если вы спрашиваете, почему он был разработан таким образом, то могут сказать только дизайнеры Framework, но я подозреваю это, потому что это тривиальная проверка, чтобы проверить, пытаетесь ли вы конвертировать из одного типа в один и тот же тип.
Учитывая, что их целью является преобразование нестроковых типов в/из строк для отображения в сетках свойств, XAML и т.д., неудивительно, что он не поддерживает полностью нестрочные преобразования.
Ответ 2
Boolean, Char, DateTime, String и Object TypeConverter наследуют от BaseTypeConverter и не перезаписывают CanConvertTo, которые возвращают true, только если переданный тип имеет строку типа. Вот почему TypeDescriptor.GetConverter(typeof(bool)).CanConvertTo(typeof(bool))
является ложным.
Преобразователи типов для байтов, двоичных, Int16, Int32, Int64, SByte, Single, UInt16, UInt32 и UInt64 все получены из BaseNumberConverter, который возвращает true для CanCovertTo для типов, которые являются строками или примитивными типами.
Десятичный наследует и от BaseNumberConverter, но поскольку он не является примитивным, он передает тип decimail в CanConvertTo, что приведет к ложному. Вот почему TypeDescriptor.GetConverter(typeof(decimal)).CanConvertTo(typeof(decimal))
является ложным.
Здесь полная диаграмма для результатов CanConvertTo
FROM/TO Bol Byt Chr DTm Dec Dbl I16 I32 I64 SBt Sng Str Obj U16 U32 U64
Boolean +
Byte + + + + + + + + + + + + +
Char +
DateTime +
Decimal + + + + + + + + + + + + +
Double + + + + + + + + + + + + +
Int16 + + + + + + + + + + + + +
Int32 + + + + + + + + + + + + +
Int64 + + + + + + + + + + + + +
SByte + + + + + + + + + + + + +
Single + + + + + + + + + + + + +
String +
Object +
UInt16 + + + + + + + + + + + + +
UInt32 + + + + + + + + + + + + +
UInt64 + + + + + + + + + + + + +
Типы и их преобразователи
Type Converter class Converter inherits from
---------- ------------------ -----------------------
Boolean BooleanConverter TypeConverter
Byte ByteConverter BaseNumberConverter
Char CharConverter TypeConverter
DateTime DateTimeConverter TypeConverter
Decimal DecimalConverter BaseNumberConverter
Double DoubleConverter BaseNumberConverter
Int16 Int16Converter BaseNumberConverter
Int32 Int32Converter BaseNumberConverter
Int64 Int64Converter BaseNumberConverter
SByte SByteConverter BaseNumberConverter
Single SingleConverter BaseNumberConverter
String StringConverter TypeConverter
Object TypeConverter Object
UInt16 UInt16Converter BaseNumberConverter
UInt32 UInt32Converter BaseNumberConverter
UInt64 UInt64Converter BaseNumberConverter
UInt32 UInt32Converter BaseNumberConverter
UInt64 UInt64Converter BaseNumberConverter