为什么我们更喜欢?到 ??C#中的运算符?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1543522/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
why do we prefer ? to ?? operator in c#?
提问by RameshVel
I recently found that we can use ?? operator to check nulls. Please check the below code samples:
我最近发现我们可以使用 ?? 运算符来检查空值。请检查以下代码示例:
var res = data ?? new data();
This is exactly similar to
这完全类似于
var res = (data==null) ? new data() : data ;
I checked my whole project source repository and some of other open source projects. And this ??
operator never been used.
我检查了我的整个项目源代码库和其他一些开源项目。而这个??
运算符从未被使用过。
I just wondering is there any reason behind this, like performance problems or something?
我只是想知道这背后是否有任何原因,例如性能问题或其他原因?
EDIT:
编辑:
I just updated my sample code based on the comments from recursive & Anton. Its a mistake in careless. :(
我刚刚根据 recursive & Anton 的评论更新了我的示例代码。这是一个粗心大意的错误。:(
采纳答案by Bob
The null coalesce operator is much clearer when checking for null, that is its main purpose. It can also be chained.
null 合并运算符在检查 null 时更加清晰,这是它的主要目的。它也可以被链接。
object a = null;
object b = null;
object c = new object();
object d = a ?? b ?? c; //d == c.
While that operator is limited to null checking, the ternary operator is not. For example
虽然该运算符仅限于空检查,但三元运算符不是。例如
bool isQuestion = true;
string question = isQuestion ? "Yes" : "No";
I think people just aren't aware of the null coalesce operator so they use the ternary operator instead. Ternary existed before C# in most C style languages so if you don't know C# inside and out and/or you programmed in another language, ternary is a natural choice. If you are checking for null though, use the null coalesce operator, it is designed for that, and the IL is slightly optimized (compare ?? to an if then else).
我认为人们只是不知道空合并运算符,所以他们改用三元运算符。在大多数 C 风格语言中,三元存在于 C# 之前,因此如果您不了解 C# 和/或您使用另一种语言进行编程,三元是一个自然的选择。如果您正在检查 null,请使用 null 合并运算符,它是为此而设计的,并且 IL 稍微优化(比较 ?? 与 if then else)。
Here is an example comparing the use of each
这是一个比较每个使用的示例
object a = null;
object b = null;
object c = null;
object nullCoalesce = a ?? b ?? c;
object ternary = a != null ? a : b != null ? b : c;
object ifThenElse;
if (a != null)
ifThenElse = a;
else if (b != null)
ifThenElse = b;
else if (c != null)
ifThenElse = c;
First, just look at the syntax for null coalesce, it is way clearer. Ternary is really confusing. Now lets look at the IL
首先,看看空合并的语法,它更清晰。三元真的很混乱。现在让我们看看 IL
Null Coalesce Only
仅空合并
.entrypoint
.maxstack 2
.locals init (
[0] object a,
[1] object b,
[2] object c,
[3] object nullCoalesce)
L_0000: ldnull
L_0001: stloc.0
L_0002: ldnull
L_0003: stloc.1
L_0004: newobj instance void [mscorlib]System.Object::.ctor()
L_0009: stloc.2
L_000a: ldloc.0
L_000b: dup
L_000c: brtrue.s L_0015
L_000e: pop
L_000f: ldloc.1
L_0010: dup
L_0011: brtrue.s L_0015
L_0013: pop
L_0014: ldloc.2
L_0015: stloc.3
L_0016: ldloc.3
L_0017: call void [mscorlib]System.Console::WriteLine(object)
L_001c: ret
Ternary Only
仅三元
.entrypoint
.maxstack 2
.locals init (
[0] object a,
[1] object b,
[2] object c,
[3] object ternary)
L_0000: ldnull
L_0001: stloc.0
L_0002: ldnull
L_0003: stloc.1
L_0004: newobj instance void [mscorlib]System.Object::.ctor()
L_0009: stloc.2
L_000a: ldloc.0
L_000b: brtrue.s L_0016
L_000d: ldloc.1
L_000e: brtrue.s L_0013
L_0010: ldloc.2
L_0011: br.s L_0017
L_0013: ldloc.1
L_0014: br.s L_0017
L_0016: ldloc.0
L_0017: stloc.3
L_0018: ldloc.3
L_0019: call void [mscorlib]System.Console::WriteLine(object)
L_001e: ret
If Then Else Only
如果那么只有
.entrypoint
.maxstack 1
.locals init (
[0] object a,
[1] object b,
[2] object c,
[3] object ifThenElse)
L_0000: ldnull
L_0001: stloc.0
L_0002: ldnull
L_0003: stloc.1
L_0004: newobj instance void [mscorlib]System.Object::.ctor()
L_0009: stloc.2
L_000a: ldloc.0
L_000b: brfalse.s L_0011
L_000d: ldloc.0
L_000e: stloc.3
L_000f: br.s L_001a
L_0011: ldloc.1
L_0012: brfalse.s L_0018
L_0014: ldloc.1
L_0015: stloc.3
L_0016: br.s L_001a
L_0018: ldloc.2
L_0019: stloc.3
L_001a: ldloc.3
L_001b: call void [mscorlib]System.Console::WriteLine(object)
L_0020: ret
IL isn't one of my strong points, so maybe someone can edit my answer and expand on it. I was going to explain my theory, but I'd rather not confuse myself and others. The number of LOC is similar for all three, but not all IL operators take the same length of time to execute.
IL 不是我的强项之一,所以也许有人可以编辑我的答案并对其进行扩展。我打算解释我的理论,但我不想混淆我自己和其他人。所有三个的 LOC 数量相似,但并非所有 IL 操作符执行的时间长度都相同。
回答by Binoj Antony
回答by Rytmis
The ?? operator (also known as the null-coalescing operator) is less known than the ternary operator, as it made its debut with .NET 2.0 and Nullable Types. Reasons for not using it probably include not begin aware that it exists, or being more familiar with the ternary operator.
这 ??运算符(也称为空合并运算符)不如三元运算符广为人知,因为它在 .NET 2.0 和 Nullable 类型中首次亮相。不使用它的原因可能包括不知道它存在,或者更熟悉三元运算符。
That said, checking for null is not the only thing the ternary operator is good for, so it's not a replacement for it as such, more like a better alternative for a very specific need. :)
也就是说,检查 null 并不是三元运算符唯一擅长的事情,因此它本身并不是它的替代品,更像是针对特定需求的更好替代品。:)
回答by Karel Bílek
I think it's just a habit from other languages. AFAIK, ?? operator is not used in any other language.
我认为这只是其他语言的习惯。AFAIK, ??运算符未在任何其他语言中使用。
回答by Bryan
I would have thought the equivalent of
我会认为相当于
var res = data ?? data.toString();
would be
将是
var res = (data!=null) ? data : data.toString();
回答by Fredrik M?rk
One reason (as others have already touched) is likely to be lack of awareness. It could also be (as in my own case), a wish to keep the number of approaches to do similar things in a code base down as much as possible. So I tend to use the ternary operator for all compact if-a-condition-is-met-do-this-otherwise-do-that situations.
一个原因(正如其他人已经触及的)可能是缺乏意识。也可能是(如我自己的情况),希望尽可能减少在代码库中执行类似操作的方法数量。所以我倾向于在所有紧凑的 if-a-condition-is-met-do-this-otherwise-do-that 情况下使用三元运算符。
For instance, I find the following two statements rather similar on a conceptual level:
例如,我发现以下两个陈述在概念层面上相当相似:
return a == null ? string.Empty : a;
return a > 0 ? a : 0;
回答by Matthew Whited
Based on Bob'sanswer
基于鲍勃的回答
public object nullCoalesce(object a, object b, object c)
{
return a ?? b ?? c;
}
public object ternary(object a, object b, object c)
{
return a != null ? a : b != null ? b : c;
}
public object ifThenElse(object a, object b, object c)
{
if (a != null)
return a;
else if (b != null)
return b;
else
return c;
}
... this is the IL from release builds ...
...这是来自发布版本的 IL ...
.method public hidebysig instance object nullCoalesce(
object a,
object b,
object c) cil managed
{
.maxstack 8
L_0000: ldarg.1
L_0001: dup
L_0002: brtrue.s L_000b
L_0004: pop
L_0005: ldarg.2
L_0006: dup
L_0007: brtrue.s L_000b
L_0009: pop
L_000a: ldarg.3
L_000b: ret
}
.method public hidebysig instance object ternary(
object a,
object b,
object c) cil managed
{
.maxstack 8
L_0000: ldarg.1
L_0001: brtrue.s L_000a
L_0003: ldarg.2
L_0004: brtrue.s L_0008
L_0006: ldarg.3
L_0007: ret
L_0008: ldarg.2
L_0009: ret
L_000a: ldarg.1
L_000b: ret
}
.method public hidebysig instance object ifThenElse(
object a,
object b,
object c) cil managed
{
.maxstack 8
L_0000: ldarg.1
L_0001: brfalse.s L_0005
L_0003: ldarg.1
L_0004: ret
L_0005: ldarg.2
L_0006: brfalse.s L_000a
L_0008: ldarg.2
L_0009: ret
L_000a: ldarg.3
L_000b: ret
}