empty - C#if-null-then-null expresión
null c# operator (6)
Solo por curiosidad / conveniencia: C # proporciona dos características de expresión condicional que conozco:
string trimmed = (input == null) ? null : input.Trim();
y
string trimmed = (input ?? "").Trim();
Extraño otra expresión similar para una situación que enfrento muy a menudo:
Si la referencia de entrada es nula, entonces la salida debería ser nula. De lo contrario, la salida debería ser el resultado de acceder a un método o propiedad del objeto de entrada.
He hecho exactamente eso en mi primer ejemplo, pero (input == null) ? null : input.Trim()
(input == null) ? null : input.Trim()
es bastante detallado e ilegible.
¿Hay otra expresión condicional para este caso, o puedo usar el ??
operador elegantemente?
¿Algo como el operador de anulación de la seguridad de Groovy?
string zipCode = customer?.Address?.ZipCode;
Supongo que el equipo de C # ha mirado esto y descubrió que no es tan sencillo de diseñar con elegancia como se podría esperar ... aunque no he escuchado sobre los detalles de los problemas.
No creo que haya algo así en el idioma en este momento, me temo ... y no he escuchado ningún plan para hacerlo, aunque eso no quiere decir que no suceda en algún momento.
EDIT: Ahora va a ser parte de C # 6, como el "operador condicional nulo".
Actualmente solo podemos escribir un método de extensión si no quieres repetirte, me temo.
public static string NullableTrim(this string s)
{
return s == null ? null : s.Trim();
}
Como solución alternativa, puede utilizar esto, que se basa en la mónada Maybe .
public static Tout IfNotNull<Tin, Tout>(this Tin instance, Func<Tin, Tout> Output)
{
if (instance == null)
return default(Tout);
else
return Output(instance);
}
Úsalo de esta manera:
int result = objectInstance.IfNotNull(r => 5);
var result = objectInstance.IfNotNull(r => r.DoSomething());
No hay nada incorporado, pero podrías envolverlo todo en un método de extensión si quisieras (aunque probablemente no me molestaría).
Para este ejemplo específico:
string trimmed = input.NullSafeTrim();
// ...
public static class StringExtensions
{
public static string NullSafeTrim(this string source)
{
if (source == null)
return source; // or return an empty string if you prefer
return source.Trim();
}
}
O una versión más general:
string trimmed = input.IfNotNull(s => s.Trim());
// ...
public static class YourExtensions
{
public static TResult IfNotNull<TSource, TResult>(
this TSource source, Func<TSource, TResult> func)
{
if (func == null)
throw new ArgumentNullException("func");
if (source == null)
return source;
return func(source);
}
}
Puede elegir entre una clase Nullify
personalizada o un método de extensión NullSafe
como se describe aquí: http://qualityofdata.com/2011/01/27/nullsafe-dereference-operator-in-c/
El uso será el siguiente:
//Groovy:
bossName = Employee?.Supervisor?.Manager?.Boss?.Name
//C# Option 1:
bossName = Nullify.Get(Employee, e => e.Supervisor, s => s.Manager,
m => m.Boss, b => b.Name);
//C# Option 2:
bossName = Employee.NullSafe( e => e.Supervisor ).NullSafe( s => s.Boss )
.NullSafe( b => b.Name );
Tuve el mismo problema que escribí algunos pequeños métodos de extensión:
public static TResult WhenNotNull<T, TResult>(
this T subject,
Func<T, TResult> expression)
where T : class
{
if (subject == null) return default(TResult);
return expression(subject);
}
public static TResult WhenNotNull<T, TResult>(
this T subject, Func<T, TResult> expression,
TResult defaultValue)
where T : class
{
if (subject == null) return defaultValue;
return expression(subject);
}
public static void WhenNotNull<T>(this T subject, Action<T> expression)
where T : class
{
if (subject != null)
{
expression(subject);
}
}
Lo usas así;
string str = null;
return str.WhenNotNull(x => x.Length);
o
IEnumerable<object> list;
return list.FirstOrDefault().WhenNotNull(x => x.id, -1);
o
object obj;
IOptionalStuff optional = obj as IOptionalStuff;
optional.WhenNotNull(x => x.Do());
También hay sobrecargas para tipos anulables.