The null-coalescing operator and throw
According to https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-7.0/throw-expression
a throw expression consists of the throw keyword followed by a null_coalescing_expression where the null_coalescing_expression
must denote a value of the class type System.Exception, of a class
type that derives from System.Exception or of a type parameter type
that has System.Exception (or a subclass thereof) as its effective
base class. If evaluation of the expression produces null, a
System.NullReferenceException is thrown instead
return name ?? throw;
does not satisfy this condition as only the throw expression would be allowed here, not a throw statement.
At least that's how I read this.
Is there an opposite to the null coalescing operator? (…in any language?)
There's the null-safe dereferencing operator (?.) in Groovy... I think that's what you're after.
(It's also called the safe navigation operator.)
For example:
homePostcode = person?.homeAddress?.postcode
This will give null if person
, person.homeAddress
or person.homeAddress.postcode
is null.
(This is now available in C# 6.0 but not in earlier versions)
C#: Null coalescing operator using nullable bool giving (what I consider) incorrect result
Take a look at the table here: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/#operator-precedence
The operator precedence of the null-coalescing operator ??
is lower than the conditional or operator ||
.
This means your code is being evaluated as:
Console.WriteLine(nullableBoolEqualFalse ?? (false || true));
false || true
evaluates to true
, and nullableBoolEqualFalse ?? true
evaluates to nullableBoolEqualFalse
which is why you are seeing false
in the output.
C# compiling optimizations: null coalescing operator - UPDATED - Reflector's bug?
This looks like a bug in Reflector's C# disassembly.
Starting with this code:
public static string _test;
public static string _setting;
public static string Test_1
{
get { return _test ?? (_setting ?? "default"); }
}
Reflector shows this C# disassembly:
public static string Test_1
{
get
{
return (_test ?? (_setting ?? "default"));
}
}
and the corresponding IL:
.method public hidebysig specialname static string get_Test_1() cil managed
{
.maxstack 8
L_0000: ldsfld string ConsoleApplication1.Program::_test
L_0005: dup
L_0006: brtrue.s L_0017
L_0008: pop
L_0009: ldsfld string ConsoleApplication1.Program::_setting
L_000e: dup
L_000f: brtrue.s L_0017
L_0011: pop
L_0012: ldstr "default"
L_0017: ret
}
I am not an IL expert, but this is my take on it:
L_0000:
ldsfld
pushes_test
onto the evaluation stackL_0005:
dup
copies the value (_test
) that is topmost on the evaluation stack and pushes that onto the stack.L_0006:
brtrue.s
pops the value created bydup
off the stack and jumps toL_0017
if it is notnull
.L_0008:
pop
at this point,_test
isnull
, so pop that value off the stack.
and it continues to evaluate _setting
in a similar fashion, finally returning "default"
if _setting
is also null
.
Now, if we add an assignment into the code like this:
public static string Test_2
{
get { return _test ?? (_test = (_setting ?? "default")); }
}
Reflector shows this C# disassembly:
public static string Test_2
{
get
{
if (_test == null)
{
string text1 = _test;
}
return (_test = _setting ?? "default");
}
}
which is not correct (if _test
is not null
, instead of returning _test
, it assigns _setting
or "default"
to _test
and then returns).
However, the IL dissassembly looks like the IL for Test_1
, with a couple of extra instructions at L_0017
and L_0018
to do the assignment.
.method public hidebysig specialname static string get_Test_2() cil managed
{
.maxstack 8
L_0000: ldsfld string ConsoleApplication1.Program::_test
L_0005: dup
L_0006: brtrue.s L_001d
L_0008: pop
L_0009: ldsfld string ConsoleApplication1.Program::_setting
L_000e: dup
L_000f: brtrue.s L_0017
L_0011: pop
L_0012: ldstr "default"
L_0017: dup
L_0018: stsfld string ConsoleApplication1.Program::_test
L_001d: ret
}
Finally, if you copy Reflector's C# dissembly and run it against the original, you'll see it produces different results.
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
_test = "Test";
Console.WriteLine(Test_2);
Console.WriteLine(Reflector_Test_2);
Console.ReadLine();
}
public static string _test;
public static string _setting;
public static string Test_1
{
get { return _test ?? (_setting ?? "default"); }
}
public static string Test_2
{
get { return _test ?? (_test = (_setting ?? "default")); }
}
public static string Reflector_Test_2
{
get
{
if (_test == null)
{
string text1 = _test;
}
return (_test = _setting ?? "default");
}
}
}
}
Outputs
Test
default
Coalesce operator in C#?
Yup:
tb_myTextBox.Text = o.Member ?? "default";
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-coalescing-operator
What does question mark and dot operator ?. mean in C# 6.0?
It's the null conditional operator. It basically means:
"Evaluate the first operand; if that's null, stop, with a result of null. Otherwise, evaluate the second operand (as a member access of the first operand)."
In your example, the point is that if a
is null
, then a?.PropertyOfA
will evaluate to null
rather than throwing an exception - it will then compare that null
reference with foo
(using string's ==
overload), find they're not equal and execution will go into the body of the if
statement.
In other words, it's like this:
string bar = (a == null ? null : a.PropertyOfA);
if (bar != foo)
{
...
}
... except that a
is only evaluated once.
Note that this can change the type of the expression, too. For example, consider FileInfo.Length
. That's a property of type long
, but if you use it with the null conditional operator, you end up with an expression of type long?
:
FileInfo fi = ...; // fi could be null
long? length = fi?.Length; // If fi is null, length will be null
Why do i need to put the null-coalescing operator in brackets?
v1
is 0 for the exact reason you mentioned: the null-coalescing operator actually has relatively low precedence. This table shows exactly how low.
So for the first expression, 1 + null
is evaluated first, and it evaluates to a null int?
, which then coalesces to 0.
Is there a practical use for regular OR (|) and regular AND (&) operator
As you say, these operators don't short-circuit. But that's not all: they're used for bit manipulation. Some examples:
Set the 4th bit:
// 00000010 | 00001000 == 00001010
value = value | (1 << 3);
Clear the 4th bit:
// ~00001000 == 11110111
// 00001010 & 11110111 == 00000010
value = value & ~(1 << 3);
Check if the 4th bit is set:
// 00001010 & 00001000 == 00001000
if ((value & (1 << 3)) != 0)
...
In C#, this is commonly used with flag enums (enum
types with the [Flags]
attribute applied).
Here's an example from the framework:
[Flags]
public enum FileAttributes
{
ReadOnly = 0x1,
Hidden = 0x2,
System = 0x4,
Directory = 0x10,
Archive = 0x20,
Device = 0x40,
Normal = 0x80,
// and so on...
}
So for instance you could test if a file is hidden using code like:
if ((attributes & FileAttributes.Hidden) != 0)
...
Related Topics
Include Files from Parent or Other Directory
How to Get Greenwich Mean Time in PHP
Run Cron Job on PHP Script, on Localhost in Windows
PHP Function Use Variable from Outside
Save PHP Variables to a Text File
How to Convert Word Smart Quotes and Em Dashes in a String
How to Create Installer for Website. PHP MySQL
What Are .Tpl Files? PHP, Web Design
HTML Upload Max_File_Size Does Not Appear to Work
Test If Port Open and Forwarded Using PHP
How to Get Time Zone Through Ip Address in PHP
What Security Issues Should I Look Out for in PHP
Regex to Detect Invalid Utf-8 String
Getting Pear to Work on Xampp (Apache/MySQL Stack on Windows)