C# 类型转换器行为不一致?
我正在研究一个C# 类型转换器行为不一致?,c#,typeconverter,C#,Typeconverter,我正在研究一个IValueConverter实现,它将转换bool?值。为了通用性,我决定使用TypeConverter将输入值转换为bool?。由于它的主要用途是用作XAML绑定的转换器,我希望避免抛出异常,因为它会导致UI性能的显著降低。为此,我尝试使用TypeConverter.IsValid方法,但遇到了特殊的行为,下面的代码中显示了一个例子: //returned converter is a NullableConverter var converter = TypeDescript
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);
也许我错了,但我希望IsValid
方法在值无法转换时返回false
,否则返回true
,但对于空字符串和NullableConverter
(对于其他可空类型也可以观察到相同的行为)
这是一个bug还是一个设计选择?如果是后者,还有其他类似的情况吗
编辑
在检查了forNullableConverter
之后,我想我已经找到了这种行为的原因。以下是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);
}
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);
}
}
在我的例子中,simpleTypeConverter
属于BooleanConverter
类型,可以理解,它为string.Empty返回false
。另一方面,下面是来自
实现的转换:
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);
}
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);
}
}
显然,string.Empty
属于第二个if
语句,因此null
结果没有异常
知道这种行为的原因,问题仍然存在——这是一种疏忽,还是有意这样做?我已经提交了一份报告,并将发表任何结论。不同的人在某些情况下的期望可能不一样,但对我来说,框架在这种情况下给出的行为似乎是合理的
例如:在以下情况下,我认为这种行为是完全合理的
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
从@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"
ConvertToString
正在做一些我觉得很好的事情。请注意,var isNullAString=null是string
返回false
!对我来说,将null转换为空字符串更有意义,即使这不是您所期望的
至于你问题中最后一个未解决的部分
也许我错了,但我希望IsValid方法在无法转换值时返回false,否则返回true,但对于空字符串和NullableConverter,情况显然不是这样(对于其他nullable类型,可以观察到相同的行为)
我相信这在上面的评论中得到了令人满意的回答
IsValid方法用于验证类型中的值,而不是确定值是否可以转换为给定类型。例如,IsValid可用于确定给定值是否对枚举类型有效
出现此问题的原因是String.Empty是一个类,而“”是一个文本。它是一个只读变量。这意味着它是一个字符串类型的空变量。当我尝试您的示例时,IsValid
抛出一个FormatException
,消息字符串未被识别为有效的布尔值。
但是,文档中说从.NET Framework 4开始,IsValid方法捕获CanConvertFrom和ConvertFrom方法的异常。如果输入值类型导致CanConvertFrom返回false,或者输入值导致ConvertFrom引发异常,IsValid方法将返回false
返回一个空字符串。我猜null
对于null
无效?@MariusBancila我刚刚测试了从2.0到4.5.1的代码目标框架版本,在任何情况下,ConvertFrom
和IsValid
都不会引发异常。不过有趣的是,直到并包括版本3.5IsValid
返回true
…是否有可能ConvertFrom
会“吞咽”异常?根据文档,它应该吞咽从.NET 4.0开始的异常。但是我在.NET 4.5项目中进行了测试。因此我没有得到它。这不是一个bug。根据TypeConverter.IsValid的MSDN描述:IsValid方法用于验证类型中的值,而不是确定值是否可以转换为给定类型。例如,IsValid可用于确定给定值是否对枚举类型有效。”