只是为了好奇/方便:C#提供了两个我知道的很酷的条件表达式功能:
string trimmed = (input == null) ? null : input.Trim();
和
string trimmed = (input ?? "").Trim();
对于我经常遇到的情况,我想念另一个这样的表达:
如果输入引用为null,则输出应为null。否则,输出应该是访问输入对象的方法或属性的结果。
我在第一个例子中完成了这一点,但是(input == null) ? null : input.Trim()
非常详细且难以理解。
这种情况是否有另一个条件表达式,或者我可以优雅地使用??
运算符吗?
答案 0 :(得分:48)
像Groovy的null-safe解引用运算符?
string zipCode = customer?.Address?.ZipCode;
我认为C#团队已经对此进行了研究,发现设计优雅并不像人们想象的那么简单......虽然我没有听说过问题的细节。
我不相信此刻语言中有任何此类内容,我担心......而且我还没有听说过任何计划,尽管这并不是说它不会发生在某些地方点。
编辑:它现在将成为C#6的一部分,作为“零条件运算符”。答案 1 :(得分:10)
您可以选择自定义Nullify
课程或NullSafe
扩展方法,如下所述:http://qualityofdata.com/2011/01/27/nullsafe-dereference-operator-in-c/
用法如下:
//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 );
答案 2 :(得分:9)
目前我们只能写一个扩展方法,如果你不想重复自己,我担心。
public static string NullableTrim(this string s)
{
return s == null ? null : s.Trim();
}
答案 3 :(得分:7)
作为一种解决方法,您可以使用基于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());
答案 4 :(得分:5)
没有任何内置功能,但如果您愿意,可以将其全部包含在扩展方法中(尽管我可能不会打扰)。
对于这个具体的例子:
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);
}
}
答案 5 :(得分:4)
我遇到了同样的问题,我写了几个小扩展方法:
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());
可空类型也有重载。