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的重载。