c# typeconverter

c# - ¿Inconsistencia en el comportamiento de TypeConverter?



(2)

Estoy trabajando en una implementación de IValueConverter que convertiría bool? valores. En aras de la versatilidad, he decidido utilizar TypeConverter para convertir el valor de entrada en bool? . Dado que su propósito principal es ser utilizado como un convertidor para los enlaces XAML, me gustaría evitar que se produzcan excepciones, ya que resulta en una disminución significativa del rendimiento de la interfaz de usuario. Para hacerlo, intenté usar el método TypeConverter.IsValid , pero encontré un comportamiento peculiar, cuyo ejemplo se muestra en el siguiente código:

//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);

Quizás me equivoque, pero esperaría que el método IsValid devuelva false siempre que un valor no pueda convertirse y sea true otra manera, pero claramente ese no es el caso con una cadena vacía y NullableConverter (se puede observar el mismo comportamiento para otros tipos anulables) .

¿Es esto un error o más bien una elección de diseño? Y si esto último, ¿hay otros casos similares?

EDITAR

Después de inspeccionar el código fuente de NullableConverter , creo que he encontrado la razón de este comportamiento. Aquí está la implementación de 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); }

En mi caso, el simpleTypeConverter es de tipo BooleanConverter y, comprensiblemente, devuelve false para string.Empty . Por otro lado, aquí está la implementación de 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); } }

Obviamente, string.Empty cae en la segunda instrucción if , de ahí el resultado null sin una excepción.

Sabiendo la razón de este comportamiento, la pregunta sigue siendo: ¿es un descuido o está destinado a funcionar de esta manera? He enviado un informe de error y publicaré cualquier conclusión que salga de él.


La razón por la que tiene el problema es porque String.Empty es una clase vs "" es un Literal. Es un Varialble ReadOnly. lo que significa que es una variable nula de tipo cadena.


Lo que las diferentes personas esperan en algunas de estas situaciones probablemente no sea lo mismo, pero para mí el comportamiento dado por el marco en este caso parece razonable.

Por ejemplo: en los siguientes casos, el comportamiento me parece perfectamente razonable.

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

Del comentario de @C.Evenhuis, este es el comportamiento que creo que se consideró cuestionable.

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 está haciendo algo que me parece muy bueno. Si nota, var isNullAString = null is string devuelve false ! Tiene más sentido para mí que el nulo se convierta en una cadena vacía, incluso si eso no es lo que esperabas.

En cuanto a la última parte no abordada en su pregunta ...

Quizás me equivoque, pero esperaría que el método IsValid devuelva falso siempre que un valor no pueda convertirse y sea verdadero de otra manera, pero claramente ese no es el caso con una cadena vacía y NullableConverter (se puede observar el mismo comportamiento para otros tipos anulables) .

Creo que esto fue respondido satisfactoriamente en un comentario anterior, que declaró

El método IsValid se usa para validar un valor dentro del tipo en lugar de determinar si el valor se puede convertir al tipo dado. Por ejemplo, se puede usar IsValid para determinar si un valor dado es válido para un tipo de enumeración.