Я работаю над реализацией IValueConverter, которая преобразует значения bool?. Ради универсальности я решил использовать TypeConverter для преобразования входного значения в bool?. Поскольку его основная цель заключается в использовании конвертера для привязок XAML, я бы хотел избежать исключения, поскольку это привело к значительному снижению производительности пользовательского интерфейса. Для этого я попытался использовать метод 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 (такое же поведение наблюдается и для других типов с нулевым значением).
Это ошибка или, скорее, выбор дизайна? И если последнее, есть ли другие подобные случаи?
ИЗМЕНИТЬ
После проверки исходного кода для 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);
}
В моем случае simpleTypeConverter имеет тип BooleanConverter и, по понятным причинам, он возвращает false для string.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 не содержит исключения.
Зная причину такого поведения, вопрос все еще остается - это надзор, или он намерен работать таким образом? Я отправил отчет об ошибке и опубликую любые выводы, чтобы выйти из него.