2015-05-23 35 views
17

我正在致力於IValueConverter實現,該值將轉換bool?值。爲了多功能性,我決定使用TypeConverter將輸入值轉換爲bool?。由於它的主要目的是作爲XAML綁定的轉換器,所以我想避免拋出異常,因爲它會導致UI性能顯着下降。要做到這一點我試着用TypeConverter.IsValid方法,而是跨越奇特的行爲來,被顯示在下面的代碼示例:TypeConverter行爲不一致?

//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每當一個值不能被轉換,並且其他情況下,但是很明顯這不是空字符串和NullableConverter(對於其他可空類型可以觀察到相同的行爲)。

這是錯誤還是設計選擇?如果是後者,是否還有其他類似的情況?

編輯

檢查source codeNullableConverter後,我想我已經找到了這種現象的原因。這裏的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); 
}   

在我的情況下simpleTypeConverterBooleanConverter型的,可以理解,它返回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); 
    } 
} 

顯然,string.Empty落入第二if聲明,因此null結果無異常。

瞭解這種行爲的原因,問題仍然存在 - 這是一個疏忽,還是打算以這種方式工作?我已提交bug report,並會發布任何結論。

+2

當我嘗試你的例子'IsValid'拋出'FormatException'與消息'字符串不被識別爲有效的布爾.'然而,文檔說「從.NET Framework 4開始,IsValid方法捕獲CanConvertFrom和ConvertFrom方法如果輸入值類型導致CanConvertFrom返回false,或者如果輸入值導致ConvertFrom引發異常,則IsValid方法返回false。 –

+0

另外有趣的是'myNullableConverter.ConvertToString(null)'返回一個空字符串。我猜'null'對'Nullable '無效? –

+1

@MariusBancila我剛剛測試了範圍從2.0到4.5.1的代碼定位框架版本,並且在任何情況下都沒有'ConvertFrom'和'IsValid'引發異常。有趣的是,直到幷包括版本3.5「IsValid」返回了「true」......是否有可能'ConvertFrom'「吞下」異常? – Grx70

回答

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 

來自@ 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 is string返回false!對於我而言,將null轉換爲空字符串更有意義,即使這不符合您的期望。

至於你的問題中最後一個未解決的部分..

也許我錯了,但是我希望和isValid方法返回false時的值不能轉換和真實,否則,但顯然這不是一個空字符串,並NullableConverter的情況下(相同的行爲可以觀察其他可空類型)。

我相信這是令人滿意的在上述評論,其中指出

所述的IsValid方法用於驗證的類型內的值,而不是決定是否值可以轉換爲給定類型的回答。例如,可以使用IsValid來確定給定值對於枚舉類型是否有效。

0

您遇到問題的原因是因爲String.Empty是一個類vs「」是一個文字。它是一個只讀Varialble。這意味着它是一個字符串類型的NULL變量。