C # if-null-then-null expression

Solo por curiosidad / conveniencia: C # proporciona dos excelentes funciones 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 debe 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 desreferenciación nulo seguro de Groovy?

 string zipCode = customer?.Address?.ZipCode; 

Deduzco que el equipo de C # ha analizado esto y ha descubierto que no es tan simple diseñar con elegancia como cabría esperar … aunque no he oído hablar de los detalles de los problemas.

No creo que haya algo en el lenguaje en este momento, me temo … y no he oído hablar de ningún plan para eso, aunque eso no quiere decir que no vaya a suceder en algún momento.

EDITAR: Ahora va a ser parte de C # 6, como el “operador condicional nulo”.

Puede elegir entre una clase personalizada Nullify 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 ); 

Actualmente, solo te escribo un método de extensión si no quieres repetirlo.

 public static string NullableTrim(this string s) { return s == null ? null : s.Trim(); } 

Como solución alternativa puede usar esto que se basa en Maybe Monada .

 public static Tout IfNotNull(this Tin instance, Func Output) { if (instance == null) return default(Tout); else return Output(instance); } 

Úselo de esta manera:

 int result = objectInstance.IfNotNull(r => 5); var result = objectInstance.IfNotNull(r => r.DoSomething()); 

No hay nada integrado, pero podrías envolverlo todo en un método de extensión si así lo deseas (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( this TSource source, Func func) { if (func == null) throw new ArgumentNullException("func"); if (source == null) return source; return func(source); } } 

Tuve el mismo problema. Escribí algunos pequeños métodos de extensión:

 public static TResult WhenNotNull( this T subject, Func expression) where T : class { if (subject == null) return default(TResult); return expression(subject); } public static TResult WhenNotNull( this T subject, Func expression, TResult defaultValue) where T : class { if (subject == null) return defaultValue; return expression(subject); } public static void WhenNotNull(this T subject, Action expression) where T : class { if (subject != null) { expression(subject); } } 

Lo usas así;

 string str = null; return str.WhenNotNull(x => x.Length); 

o

 IEnumerable 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 los tipos que aceptan nulos.