TypeConverter行为不一致?

Grx*_*x70 17 c# typeconverter

我正在开发一个IValueConverter可以转换bool?值的实现.为了多功能性,我决定使用TypeConverter将输入值转换为bool?.由于它的主要目的是用作XAML绑定的转换器,因此我希望避免抛出异常,因为它会导致UI性能的显着降低.为此,我尝试使用TypeConverter.IsValid方法,但遇到了特殊的行为,其示例在以下代码中显示:

//returned converter is a NullableConverter
var converter = TypeDescriptor.GetConverter(typeof(bool?));

//this method returns false
converter.IsValid(string.Empty);

//yet this method returns null without throwing an exception
converter.ConvertFrom(string.Empty);
Run Code Online (Sandbox Code Playgroud)

也许我错了,但是我希望只要一个值无法转换就会IsValid返回该方法false,true否则,但显然不是空字符串的情况NullableConverter(对于其他可以为空的类型可以观察到相同的行为).

这是一个错误还是设计选择?如果是后者,还有其他类似案例吗?

编辑

在检查源代码后,NullableConverter我想我已经找到了这种行为的原因.这是IsValid实施:

public override bool IsValid(ITypeDescriptorContext context, object value) {
    if (simpleTypeConverter != null) {
        object unwrappedValue = value;
        if (unwrappedValue == null) {
            return true; // null is valid for nullable.
        }
        else {
            return simpleTypeConverter.IsValid(context, unwrappedValue);
        }
    }

    return base.IsValid(context, value);
}        
Run Code Online (Sandbox Code Playgroud)

在我的情况simpleTypeConverter是类型的BooleanConverter,可以理解,它返回falsestring.Empty.另一方面,这是ConvertFrom实现:

public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) {
    if (value == null || value.GetType() == this.simpleType) {
        return value;
    }
    else if (value is String && String.IsNullOrEmpty(value as String)) {
        return null;
    }
    else if (this.simpleTypeConverter != null) {
        object convertedValue = this.simpleTypeConverter.ConvertFrom(context, culture, value);
        return convertedValue;
    }
    else {
        return base.ConvertFrom(context, culture, value);
    }
}
Run Code Online (Sandbox Code Playgroud)

显然,string.Empty落入第二个if陈述,因此null结果没有例外.

知道这种行为的原因仍然存在问题 - 这是一种疏忽,还是打算以这种方式工作?我已经提交了一份错误报告,并将发布任何结论.

Fra*_*yce 1

不同的人在某些情况下的期望可能不同,但对我来说,在这种情况下框架给出的行为似乎是合理的。

例如:在以下情况下,这种行为对我来说似乎完全合理。

var converter = TypeDescriptor.GetConverter(typeof(bool?));

bool? nullableBool1 = converter.ConvertFrom(string.Empty); // returns null
bool? nullableBool2 = converter.ConvertFrom("true"); // returns true
bool? nullableBool3 = converter.ConvertFrom("false"); // returns false

bool? nullableBool4 = converter.ConvertFromString(string.Empty); // returns null
bool? nullableBool5 = converter.ConvertFromString("true"); // returns true
bool? nullableBool6 = converter.ConvertFromString("false"); // returns false
Run Code Online (Sandbox Code Playgroud)

从@C.Evenhuis 的评论来看,我认为这是有问题的行为。

var converter = TypeDescriptor.GetConverter(typeof(bool?));
var string1 = converter.ConvertToString(null); // returns ""
var string2 = converter.ConvertToString(true); // returns "true"
var string3 = converter.ConvertToString(false); // returns "false"
Run Code Online (Sandbox Code Playgroud)

ConvertToString正在做一些我觉得非常好的事情。如果您注意到,var isNullAString = null is string请返回false!对我来说,将 null 转换为空字符串更有意义,即使这不是您所期望的。

至于你问题中最后一个未解决的部分..

也许我错了,但我希望 IsValid 方法在值无法转换时返回 false,否则返回 true,但显然空字符串和 NullableConverter 的情况并非如此(对于其他可空类型也可以观察到相同的行为) 。

我相信上面的评论已经对此做出了令人满意的回答,其中指出

IsValid 方法用于验证类型内的值,而不是确定值是否可以转换为给定类型。例如,IsValid 可用于确定给定值对于枚举类型是否有效。