这里的基本问题 - 我有许多代码行,如下所示:
var a = (long_expression == null) ? null : long_expression.Method();
Run Code Online (Sandbox Code Playgroud)
类似的行在这个函数中重复了很多.long_expression每次都不一样.我试图找到一种方法来避免重复long_expression,但保持这种紧凑.像是相反的东西operator ??.目前我正在考虑放弃并将其放在多行上,如:
var temp = long_expression;
var a = (temp == null) ? null : temp.Method();
Run Code Online (Sandbox Code Playgroud)
但我很好奇是否有一些我不知道的聪明语法会使这更加简洁.
Jon*_*eet 77
好吧,你可以使用这样的扩展方法:
public static TResult NullOr<TSource, TResult>(this TSource source,
Func<TSource, TResult> func) where TSource : class where TResult : class
{
return source == null ? null : func(source);
}
Run Code Online (Sandbox Code Playgroud)
然后:
var a = some_long_expression.NullOr(x => x.Method());
Run Code Online (Sandbox Code Playgroud)
或者(取决于您的C#版本)
var a = some_long_expression.NullOr(Foo.Method);
Run Code Online (Sandbox Code Playgroud)
在哪里Foo的类型some_long_expression.
我不认为我会做到这一点,虽然.我只是使用两行版本.它更简单,更不聪明 - 虽然"聪明"对于Stack Overflow来说很有趣,但对于真正的代码来说通常不是一个好主意.
var x = "";
/* try null instead */
string long_expression = "foo";
var a = ((x = long_expression) == null) ? null : x.ToUpper();
/* writes "FOO" (or nothing) followed by newline */
Console.WriteLine(a);
Run Code Online (Sandbox Code Playgroud)
初始化值x的类型必须与long_expression(此处:)的类型兼容string.使用Mono C#编译器,版本2.10.8.1(来自Debian软件包mono-gmcs = 2.10.8.1-4).
我认为C#语言真的可以使用一个新的运算符来实现这种逻辑 - 它很常见,运算符可以简化无数代码行.
我们需要的东西是"??" 或"如果为null然后"运算符,但它作为特殊''.具有"if not null"条件的点运算符.为了第一 '?' 就像"?:"if-then,第二个'?'的'if'部分 对于可空类型,表示'null'.我想我们需要一个".?" 运算符与'.'一样工作,除非它只是在左表达式为null而不是抛出异常时求值为null.我想这将是一个"dot not null"操作符(好吧,所以也许".!?"会更合乎逻辑,但是不要去那里).
所以,你这么常见的例子可能会丢失这样的冗余符号名称:
var a = long_expression.?Method();
Run Code Online (Sandbox Code Playgroud)
有大量的C#代码有嵌套的空值检查,这将大大受益.试想,如果这样做会有多好:
if (localObject != null)
{
if (localObject.ChildObject != null)
{
if (localObject.ChildObject.ChildObject != null)
localObject.ChildObject.ChildObject.DoSomething();
}
}
Run Code Online (Sandbox Code Playgroud)
可能只是:
localObject.?ChildObject.?ChildObject.?DoSomething();
Run Code Online (Sandbox Code Playgroud)
还有大量的代码,其中应该存在的空检查丢失,导致偶尔的运行时错误.所以,实际上使用新的'.?' 默认情况下,运营商会消除这些问题......我们无法扭转"."的行为,这可能是不幸的.和'.?' 在这一点上,所以只有新的'.?' 如果左侧为空,则抛出异常 - 这将是更清晰,更合乎逻辑的方式,但是破坏更改非常糟糕.虽然,有人可能会说这个特定的更改可能会解决许多隐藏的问题,并且不太可能破坏任何东西(只有代码需要抛出空引用异常).哦,嗯......一个人总能做梦......
检查null的唯一缺点就是轻微的性能损失,这绝对是为什么''.不检查null.但是,我真的认为能够使用'.?' 当你关心表现(并且知道左侧永远不会为空)时,这将是更好的方法.
在类似的说明中,对'foreach'进行检查并忽略null集合也会更好.不再需要用"if(collection!= null)"包装大多数"foreach"语句,或者更糟糕的是,养成总是使用空集合而不是null的常见习惯......在某些情况下这很好,但更糟糕的是性能问题比null检查在复杂的对象树中完成,其中大多数集合是空的(我已经看过很多).我认为没有'foreach'检查null以提供更好的性能的好意图在大多数情况下都适得其反.
Anders,做出这样的改变永远不会太晚,并添加一个编译器开关来启用它们!