C#if-null-then-nullexpression式

只是为了好奇/方便:C#提供了两个很酷的条件expression式function我知道:

string trimmed = (input == null) ? null : input.Trim(); 

 string trimmed = (input ?? "").Trim(); 

对于我经常遇到的情况,我怀念另一个这样的expression:

如果input引用为空,则输出应该为空。 否则,输出应该是访问input对象的方法或属性的结果。

我在第一个例子中完成了,但(input == null) ? null : input.Trim() (input == null) ? null : input.Trim()是相当详细和不可读的。

是否有这种情况下的另一个条件expression式,或者我可以使用?? 操作员优雅?

像Groovy的空安全解引用操作符?

 string zipCode = customer?.Address?.ZipCode; 

我认为,C#团队已经看到了这一点,发现它并不像人们期望的那样简洁高雅,尽pipe我没有听说过这些问题的细节。

我不相信现在有这样的语言,恐怕……我还没有听说过任何计划,尽pipe这并不是说在某些时候不会发生。

编辑:它现在将成为C#6的一部分,作为“空条件运算符”。

您可以按照此处所述在自定义的Nullify类或NullSafe扩展方法之间进行select: http : NullSafe

用法如下:

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

目前我们只能写一个扩展方法,如果你不想重复自己,恐怕。

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

作为一个解决方法,你可以使用这是基于Maybe monad 。

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

这样使用它:

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

没有什么内置的,但是如果你愿意的话,你可以用扩展的方法把它包装起来(虽然我可能不会打扰)。

对于这个具体的例子:

 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(); } } 

或者更通用的版本:

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

我有同样的问题,我写了几个小扩展方法:

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

你这样使用

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

要么

 IEnumerable<object> list; return list.FirstOrDefault().WhenNotNull(x => x.id, -1); 

要么

 object obj; IOptionalStuff optional = obj as IOptionalStuff; optional.WhenNotNull(x => x.Do()); 

还有可空types的重载。