What do two question marks together mean in C#?
Asked Answered
L

18

2011

Ran across this line of code:

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

What do the two question marks mean, is it some kind of ternary operator? It's hard to look up in Google.

Laverty answered 15/1, 2009 at 14:3 Comment(4)
It's definitely not a ternary operator - it only has two operands! It's a bit like the conditional operator (which is ternary) but the null coalescing operator is a binary operator.Roofdeck
Re: last sentence in the q - for future ref, SymbolHound is great for this kind of thing e.g. symbolhound.com/?q=%3F%3F&l=&e=&n=&u= [to anyone suspicious - I'm not affiliated in any way, just like a good tool when I find one...]Griseous
Searching for C# ?? | C# '??' | C# "??" does not bring back expected results. Is the search engine testing if C# is null, and saying, No - Its actually C# - Here are your results for C# - Doh!Boaz
@ppumkin Just search for double question mark c# in Google.Furmenty
I
2646

It's the null coalescing operator, and quite like the ternary (immediate-if) operator. See also ?? Operator - MSDN.

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

expands to:

FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();

which further expands to:

if(formsAuth != null)
    FormsAuth = formsAuth;
else
    FormsAuth = new FormsAuthenticationWrapper();

In English, it means "If whatever is to the left is not null, use that, otherwise use what's to the right."

Note that you can use any number of these in sequence. The following statement will assign the first non-null Answer# to Answer (if all Answers are null then the Answer is null):

string Answer = Answer1 ?? Answer2 ?? Answer3 ?? Answer4;

Also it's worth mentioning while the expansion above is conceptually equivalent, the result of each expression is only evaluated once. This is important if for example an expression is a method call with side effects. (Credit to @Joey for pointing this out.)

Idalia answered 15/1, 2009 at 14:4 Comment(14)
@CodeBlend, it's not dangerous. If you were to expand you'd just have a series of nested if/else statements. The syntax is just strange because you're not used to seeing it.Vergne
@jm2 As long as you review what you are doing for example if you meant to have seperate not nested ifs this would not be appropriate. (Reading this really showed me a decent(ish) example of how it can be used)[rlacovara.blogspot.com/2009/07/…Fractious
@CodeBlend ..isn't that the case of "any" coding one does - to always review it :-)Florentinaflorentine
It would be useful to add link to MSDN documentation into this answer - to keep everything together. :) Because, I've found it in the next answer.Constrained
it would also asign it to All the previous answear# variables that were null correct??Fastness
@Fastness No it wouldn't. Semantically, you would have to do Answer1 ??= Answer2 to assign a value to Answer1, but ??= isn't a valid operator.Idalia
@lc simply because it doesn't unmuddy the water. There is no indicated nesting - the null coalescing here is sequential. The concept is correct though.Beverie
does the first argument get evaluated twice if it returns not-null first time? For example: x = f1() ?? f2(); would 'f1' be evaluated twice when it returns not-null first time?Brotherton
Note that the expansion is not quite correct like shown here, as the language guarantees that the left operand is only evaluated once. This is not a problem in this particular case, but when you have a more complicated expression than a local variable on the left, it becomes important.Ker
@Asker If it were right associative, would that mean that a ?? b ?? c ?? d is evaluated as a ?? (b ?? (c ?? d)) and c ?? d would be evaluated first? If so, I'm having trouble seeing how right-associativity corresponds more closely to a chain of if-else. Thanks for any info!Postfree
@MarkE.Haase Perhaps the docs changed, because now the docs you linked to say "the null-coalescing operators, lambdas, and the conditional operator ?: are right-associative.". Also, this Microsoft documentation states "The null-coalescing operators are right-associative."Postfree
@Postfree Wow, thanks for pointing that out! The old version I was looking at is here: web.archive.org/web/20141213132559/http://msdn.microsoft.com/… I deleted my previous comment since it is incorrect.Selfcontent
@Postfree It looks like the C# spec authors noticed this discrepancy in another stack overflow post and fixed it: https://mcmap.net/q/45773/-how-the-right-associative-of-null-coalescing-operator-behavesSelfcontent
@PaulC Please provide examples. Saying that it's "potentially" dangerous "maybe" is a meaningless comment.Bloxberg
R
333

Just because no-one else has said the magic words yet: it's the null coalescing operator. It's defined in section 7.12 of the C# 3.0 language specification.

It's very handy, particularly because of the way it works when it's used multiple times in an expression. An expression of the form:

a ?? b ?? c ?? d

will give the result of expression a if it's non-null, otherwise try b, otherwise try c, otherwise try d. It short-circuits at every point.

Also, if the type of d is non-nullable, the type of the whole expression is non-nullable too.

Roofdeck answered 15/1, 2009 at 14:7 Comment(3)
Nice to see that the language specification doc is still alive.Uncouple
@MustafaÖzçetin: For more recent editions, see github.com/dotnet/csharpstandardRoofdeck
This page is a useful one, thanks.Uncouple
H
81

It's the null coalescing operator.

http://msdn.microsoft.com/en-us/library/ms173224.aspx

Yes, nearly impossible to search for unless you know what it's called! :-)

EDIT: And this is a cool feature from another question. You can chain them.

Hidden Features of C#?

Hollyanne answered 15/1, 2009 at 14:5 Comment(0)
L
40

Thanks everybody, here is the most succinct explanation I found on the MSDN site:

// y = x, unless x is null, in which case y = -1.
int y = x ?? -1;
Laverty answered 15/1, 2009 at 14:9 Comment(2)
This hints at an important aspect of the ?? operator -- it was introduced to assist in working with nullable types. In your example, "x" is of type "int?" (Nullable<int>).Hexose
@vitule no, if the second operand of the null coalescing operator is non-nullable, then the result is non-nullable (and -1 is just a plain int, which is non-nullable).Abbeyabbi
M
33

enter image description here

The two question marks (??) indicate that its a Coalescing operator.

Coalescing operator returns the first NON-NULL value from a chain. You can see this youtube video which demonstrates the whole thing practically.

But let me add more to what the video says.

If you see the English meaning of coalescing it says “consolidate together”. For example below is a simple coalescing code which chains four strings.

So if str1 is null it will try str2, if str2 is null it will try str3 and so on until it finds a string with a non-null value.

string final = str1 ?? str2 ?? str3 ?? str4;

In simple words Coalescing operator returns the first NON-NULL value from a chain.

Madra answered 16/12, 2013 at 10:30 Comment(0)
G
25

?? is there to provide a value for a nullable type when the value is null. So, in your example:

FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

If formsAuth is null, the expression will return new FormsAuthenticationWrapper() to be assigned to FormsAuth.

Ganesha answered 15/1, 2009 at 14:5 Comment(0)
A
19

Others have described the "null-coalescing operator" quite well. In cases where a single test for null is required, the shortened syntax afforded by the closely related null-coalescing assignment operator ??= can add further readability (at least for C# 8.0 and later).

Legacy null test:

if (myvariable == null)
{
    myvariable = new MyConstructor();
}

Using the null-coalescing operator this can be rewritten as:

myvariable = myvariable ?? new MyConstructor();

Which can also be written with null-coalescing assignment:

myvariable ??= new MyConstructor();

Some find it more readable and succinct.

Allbee answered 10/3, 2020 at 15:37 Comment(1)
keep in mind this feature is available only in C# 8 or moreHandbarrow
F
18

It's short hand for the ternary operator.

FormsAuth = (formsAuth != null) ? formsAuth : new FormsAuthenticationWrapper();

Or for those who don't do ternary:

if (formsAuth != null)
{
  FormsAuth = formsAuth;
}
else
{
  FormsAuth = new FormsAuthenticationWrapper();
}
Firewood answered 15/1, 2009 at 14:5 Comment(2)
I've only corrected the spelling of "ternary" but really the operator you mean is the conditional operator. It happens to be the only ternary operator in C#, but at some point they might add another one, at which point "ternary" will be ambiguous but "conditional" won't.Roofdeck
It's shorthand for something you can do with the ternary (conditional) operator. In your long form, both the test (!= null) and the second formsAuth (after the ?) could be altered; in the null coalesce form, both implicitly take the values you have supplied.Competition
R
13

If you're familiar with Ruby, its ||= seems akin to C#'s ?? to me. Here's some Ruby:

irb(main):001:0> str1 = nil
=> nil
irb(main):002:0> str1 ||= "new value"
=> "new value"
irb(main):003:0> str2 = "old value"
=> "old value"
irb(main):004:0> str2 ||= "another new value"
=> "old value"
irb(main):005:0> str1
=> "new value"
irb(main):006:0> str2
=> "old value"

And in C#:

string str1 = null;
str1 = str1 ?? "new value";
string str2 = "old value";
str2 = str2 ?? "another new value";
Rice answered 30/6, 2009 at 17:16 Comment(2)
x ||= y desugars to something like x = x || y, so ?? is actually more similar to plain || in Ruby.Convertite
Note that ?? only cares about null, whereas the || operator in Ruby, as in most languages, is more about null, false, or anything that can be considered a boolean with a value of false (e.g. in some languages, ""). This is not a good or bad thing, merely a difference.Preexist
S
13

As correctly pointed in numerous answers that is the "null coalescing operator" (??), speaking of which you might also want to check out its cousin the "Null-conditional Operator" (?. or ?[) that is an operator that many times it is used in conjunction with ??

Null-conditional Operator

Used to test for null before performing a member access (?.) or index (?[) operation. These operators help you write less code to handle null checks, especially for descending into data structures.

For example:

// if 'customers' or 'Order' property or 'Price' property  is null,
// dollarAmount will be 0 
// otherwise dollarAmount will be equal to 'customers.Order.Price'

int dollarAmount = customers?.Order?.Price ?? 0; 

the old way without ?. and ?? of doing this is

int dollarAmount = customers != null 
                   && customers.Order!=null
                   && customers.Order.Price!=null 
                    ? customers.Order.Price : 0; 

which is more verbose and cumbersome.

Suez answered 30/10, 2016 at 2:43 Comment(0)
L
11

coalescing operator

it's equivalent to

FormsAuth = formsAUth == null ? new FormsAuthenticationWrapper() : formsAuth
Lightface answered 15/1, 2009 at 14:5 Comment(0)
C
11

Nothing dangerous about this. In fact, it is beautiful. You can add default value if that is desirable, for example:

CODE

int x = x1 ?? x2 ?? x3 ?? x4 ?? 0;
Cabbala answered 21/3, 2013 at 21:13 Comment(2)
So x1, x2, x3, and x4 could be Nullable types, example: int? x1 = null; Is that rightInaptitude
@KevinMeredith x1 - x4 MUST be nullable types: it makes no sense to say, effectively, "the result is 0 if x4 is a value which it can't possibly take" (null). "Nullable type" here includes both nullable value types and reference types, of course. It is a compile-time error if one or more of the chained variables (except the last one) isn't nullable.Competition
M
9

For your amusement only (knowing you are all C# guys ;-).

I think it originated in Smalltalk, where it has been around for many years. It is defined there as:

in Object:

? anArgument
    ^ self

in UndefinedObject (aka nil's class):

? anArgument
    ^ anArgument

There are both evaluating (?) and non-evaluating versions (??) of this.
It is often found in getter-methods for lazy-initialized private (instance) variables, which are left nil until really needed.

Mason answered 15/1, 2009 at 14:31 Comment(1)
sounds like wrapping ViewState with a property on a UserControl. Initialize only on the first get, if it´s not set before. =)Congratulant
A
9

Some of the examples here of getting values using coalescing are inefficient.

What you really want is:

return _formsAuthWrapper = _formsAuthWrapper ?? new FormsAuthenticationWrapper();

or

return _formsAuthWrapper ?? (_formsAuthWrapper = new FormsAuthenticationWrapper());

This prevents the object from being recreated every time. Instead of the private variable remaining null and a new object getting created on every request, this ensures the private variable is assigned if the new object is created.

Ascocarp answered 12/5, 2014 at 2:44 Comment(2)
Isn't ?? short-cut evaluated? new FormsAuthenticationWrapper(); is evaluated if and only if _formsAuthWrapper is nil.Amalia
Yes that's the whole point. You only want to call the method if the variable is null. @AmaliaAscocarp
S
8

In the simplest terms, two question marks are called the "null coalescing operator", which returns the first non-null value from the expression chain.

E.g. if you are taking a value from a nullable object and assigning it to a variable which is not nullable, then you can use this operator. i.e.

int a = 1;
int? b = null;
a = b ?? 0;

The result in the above equation stored in a would be zero, because b is null and we have used the ?? operator along with zero, which means that it will return "0" if and only if b is null.

int a = 1; 
int? b = 15;
a = b ?? 0;

In above equation, a will get value "15" because b has a valid value and is not null.
Also, you can not use ?? operator on a non nullable object.

In above examples, I used ?? 0, however a complete new equation can also be used after ?? operator, such as:

a = b ?? (x == 1 ? 10 : 15)
Servomechanism answered 3/4, 2021 at 17:34 Comment(0)
U
4

The ?? operator is called the null-coalescing operator. It returns the left-hand operand if the operand is not null; otherwise it returns the right hand operand.

int? variable1 = null;
int variable2  = variable1 ?? 100;

Set variable2 to the value of variable1, if variable1 is NOT null; otherwise, if variable1 == null, set variable2 to 100.

Unashamed answered 6/2, 2019 at 11:17 Comment(0)
A
3
FormsAuth = formsAuth ?? new FormsAuthenticationWrapper();

is equivalent to

FormsAuth = formsAuth != null ? formsAuth : new FormsAuthenticationWrapper();

But the cool thing about it is you can chain them, like other people said. The one thin not touched upon is that you can actually use it to throw an exception.

A = A ?? B ?? throw new Exception("A and B are both NULL");
Afterwards answered 31/3, 2018 at 21:22 Comment(1)
It's really great that you included examples in your post, although the question was looking for an explanation of what the operator is or does.Farhi
R
1

It's a null coalescing operator that works similarly to a ternary operator.

    a ?? b  => a !=null ? a : b 

Another interesting point for this is, "A nullable type can contain a value, or it can be undefined". So if you try to assign a nullable value type to a non-nullable value type you will get a compile-time error.

int? x = null; // x is nullable value type
int z = 0; // z is non-nullable value type
z = x; // compile error will be there.

So to do that using ?? operator:

z = x ?? 1; // with ?? operator there are no issues
Repetend answered 8/12, 2017 at 14:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.