Подтвердить что ты не робот

Несоответствие поведения TypeConverter?

Я работаю над реализацией 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 не содержит исключения.

Зная причину такого поведения, вопрос все еще остается - это надзор, или он намерен работать таким образом? Я отправил отчет об ошибке и опубликую любые выводы, чтобы выйти из него.

4b9b3361

Ответ 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 может использоваться для определения того, действительно ли заданное значение допустимо для типа перечисления.

Ответ 2

Причина, по которой у вас возникла проблема, заключается в том, что String.Empty является классом vs "" является литералом. Это ReadOnly Varialble. что означает, что это NULL Переменная типа string.