【问题标题】:TypeConverter cannot convert from some base types to same base typesTypeConverter 无法从某些基本类型转换为相同的基本类型
【发布时间】:2015-09-01 18:24:40
【问题描述】:

为什么那些返回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。

【问题讨论】:

  • 我不确定除了 BCL 团队的成员之外,是否有任何人能够真正解释这是否有实际原因,或者这是否只是一个疏忽。我确实在BaseNumberConverter.CanConvertTo 中看到了检查原始类型的逻辑,其中 Decimal 是 not,从而解释了与 Decimal 的差异。但是为什么不支持 Decimal 呢?

标签: c# type-conversion


【解决方案1】:

DecimalConverter(以及DoubleConverterInt32Converter)覆盖CanConvertTo 以表明它可以转换为字符串(因为这是base.CanConvertTo 所做的)和所有CLR 基本类型 .来自the Reference Source

public override bool CanConvertTo(ITypeDescriptorContext context, Type t) 
{
    if (base.CanConvertTo(context, t) || t.IsPrimitive) {
        return true;
    }
    return false;
}

decimal 从 CLR 的角度来看不是原始类型,因此转换器在传递 typeof(decimal) 时返回 false

BooleanConverter 不会覆盖CanConvertTo,因此它属于只允许转换为string 的基本实现:

public virtual bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) 
{
    return (destinationType == typeof(string));
}

如果您问为什么要这样设计,那么只有框架设计人员才能说,但我怀疑这是因为检查您是否尝试从一种类型转换是一项微不足道的检查为同一类型。

考虑到它们的目的是将非字符串类型转换为字符串以在属性网格、XAML 等中显示,因此它不完全支持非字符串转换也就不足为奇了。

【讨论】:

  • 我刚刚检查了反射,typeof(bool).IsPrimative 是真的,所以我不知道“从 CLR 的角度来看,布尔不是原始类型意味着什么”。
  • @DanielGimenez 我错了。有趣的是,这意味着 DecimalConverter.CanConvertTo(typeof(bool)) 返回 true,这是没有意义的。它似乎将 0 转换为 false 和其他任何东西到 true 就像 C++ 一样。
  • 我认为在@Matthieu 之前没有人想到这一点。为什么你不能将 bool 转换为数字,而你可以将数字转换为 bool 似乎是一个疏忽。
  • @DanielGimenez 我怀疑将数字转换为布尔值是原始设计的一部分 - 目的是能够将值转换为字符串(用于在属性框中显示和嵌入标记)并从字符串解析(在属性网格或标记中更改设置时)。此外,由于它不可逆(如何将 true 转换为 4?),所以不允许它是有意义的。
【解决方案2】:

BooleanCharDateTimeStringObjectTypeConverter 继承自 BaseTypeConverter 并且不要覆盖 CanConvertTo,仅当传递的类型为string 类型。这就是为什么TypeDescriptor.GetConverter(typeof(bool)).CanConvertTo(typeof(bool)) 是假的。

ByteDoubleInt16Int32Int64SByteSingleUInt16UInt32 和 @98765443 的类型转换器都是派生的来自BaseNumberConverter,对于字符串或原始类型的类型,CanCovertTo 返回 true。

Decimal 也继承自 BaseNumberConverter,但由于它不是原始类型,因此将十进制类型传递给 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-15
    • 1970-01-01
    • 1970-01-01
    • 2010-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多