Using the Null-Conditional Operator on the Left-Hand Side of an Assignment

Using the null-conditional operator on the left-hand side of an assignment

The null propagation operator returns a value. And since you must have a variable on the left hand side of an assignment, and not a value, you cannot use it in this way.

Sure, you could make things shorter by using the tenary operator, but that, on the other hand, doesn't really help the readability aspect.

Joachim Isaksson's comment on your question shows a different approach that should work.

Is there any Null-Conditional Operator like for Events.. Button?.Click +=(ss,ee)

The problem is not related to events.

The null-conditional operator is to stop an evaluation if a reference is null.

It is not applicable in the left or right part of an assignment.

If you have:

public class Test
{
public int Value;
public void Method() { }
}

You can't write:

Test v;

v?.Value = 10;

int a = v?.Value;

Because if v is null, v.Value is not evaluated.

  • So what to do with = 10 ?

  • Or what to do with a ?

Thus it is the same when adding or removing an event handler to an event variable that is null when empty.

C# event is null

Hence the compiler error to disallow such writings.

It is why you can't write:

TargetButton?.Click +=(ss,ee)=>{...}

Because what to to with (ss,ee)=>{...} if TargetButton is null?

You can say that you want the compiler ignores that.

But the compiler disallows doing such unclean thing.

What we can write is:

v?.Test();

Here is v is null the method is not called and all is fine because there is nothing right or left that the compiler does not know what to do with.

int a = v?.Value ?? 0;

Here if v is null 0 is used.

Null-conditional operators ?. and ?[]

Null-coalescing operators ?? and ??=

C# Null Conditional Operator alternative (conditional assignment)?

The behavior you are expecting:

(i.e. If refTypeInstance is null, then simply do nothing. If refTypeInstance is not null, then execute the statement)

Is not possible because of the way operators work. More specifically, you have a problem with operator precedence and how expression trees are formed based on that:

In the statement

(unit as RangeUnit).PreferredTarget = UnitType.Melee;

The assignment operator (=) would be in the root of the expression tree, with the left and the right expressions as branches.

A NullReferenceException would occur when the left hand is evaluated (before assignment). At this point the compiler has already started to evaluate the =. Since the dereference operator (.) will throw a NullReferenceException at runtime, it is safe for the compiler to just continue parsing the expression tree.

On the other hand if this statement would permitted:

(unit as RangeUnit)?.PreferredTarget = UnitType.Melee;

...the compiler would have to emit code to check whether the value of refTypeInstance is null. It could do that, but the problem is, what would the compiler do with the expression tree that it is currently going through? It can not simply go on like in the first example, because it would have to discard the = up the expression tree and the . down the tree. It would basically have to insert two alternatives of parsing the tree, one when the left of ?. is null and one when it isn't. That however would be an alteration of the control flow, which is definitely not what you expect from an operator.

Or to put it differently: when long as ?. just short-circuits the evaluation of operators down its branch of the expression tree, you would consider this an expected behavior. But in this case this would alter the behavior of a operator higher up in the expression tree, which you would definitely not expect.

How can I use Null-conditional Operators in WPF?

This has nothing to do with WPF.

You can't use the null conditional operator as the left hand side of an assignment expression, and the reason is painfully obvious:

When you write a code line like this: Instance?.Property = value;, and the Instance is null,
Instance?.Property would evaluate to null, so you would have a meaningless code line stating null = value.

This is why the compiler would not allow that. If you want to avoid a null reference exception in such cases, you have to do it the old-fashion way:

if(Instance != null)
{
Instance.Property = Value;
}

You could write it in a single line of code, but I personally find this less readable:

if(Instance != null) Instance.Property = Value;

A slightly more readable code would be two lines of code:

if(Instance != null) 
Instance.Property = Value;

A question about how properties work internally and null-conditional operators

Yes, properties are effectively syntactic sugar for methods with extra metadata, in terms of the generated code.

But that doesn't mean that the language rules for properties are always the same as for methods. The left-hand side of an assignment operator has to be a variable, property or indexer - but the expression _item?.Name is classified as a value rather than a variable. The language could have been designed to allow this, without changing how properties themselves work at all, but this is what we've got at the moment. (It's possible that this could change in the future, too.)

In other words, this isn't about how properties are implemented internally, but about the C# rules that govern how they can be used - and in particular, how the assignment operator works. In fact, you can take properties out of the equation entirely - if you use a public field in Item instead of a property, you'll see exactly the same error.

This isn't new to the null-safe dereferencing operator, either. Consider this example:

struct MutableStruct
{
public int Value { get; set; }

public void SetValue(int value) => Value = value;
}

class Test
{
static void Main()
{
Method().SetValue(10); // Valid, but not useful
Method().Value = 10; // Invalid
}

static MutableStruct Method() => new MutableStruct();
}

Here Method().Value = 10; isn't valid because the Method() expression evaluates to a value, not a variable (or a property or indexer).

Practical purpose of the null-coalescing assignment operator in C#?

A real world example would be lazy loading a backing field on first access when that backing field is null. Something like this:

private string _dbQuery;
private string DbQuery => _dbQuery ??= GetQuery(queryName);

Why can the null conditional operator be used when setting the value of a bool without using a nullable bool?

The problem is the await. The nullable is happening before the await, so it's like await (this.repository?.Exists(id)), which, when this.repository is null, turns into await (null?.Exists(id)), which turns into await (null), which crashes. The ?. isn't capable of reaching into the Task<bool> and making it Task<bool?>.

So you will either get the proper boolean, or an Exception.

null-conditional operator for date type?

Your code has a syntax error because a nullable DateTime? doesn't have a ToString() overload that takes a string format parameter, so you need to get the .Value out of the nullable to turn the nullable into a normal DateTime before you can format it

To answer your specific question about null conditional, this would then something like:

(movie.ReleaseDate.HasValue ? movie.ReleaseDate.Value.ToString("dd-MMM-yyyy") : "Not Yet"

Alsein's form using null coalesce is a lot more readable than using null conditional but his choice to say a movie was released today if it's release date is null doesn't make sense to me. I'd say we need a way of turning it into a date string only if has a value and turning it into some other string if it is null.

Consider:

movie.ReleaseDate?.ToString("dd-MMM-yyyy") ?? "Not Yet"

If release date is null ToString won't be called, and c# will skip straight to the ?? with a null result. ?? will then turn the null into a string of "Not Yet", which is what I presume a null release date might mean..

The ? also works some magic with the nullable, turning it into a DateTime if it does have a value, which is why the earlier "DateTime? doesn't have a ToString(string)" doesn't apply; by the time movie.ReleaseDate? has been evaluated, the result is either a null or a normal DateTime with a ToString that takes a format

?? is thus a good way to give a default value to a chain of calls, any one of which might be null and are protected from throwing null reference by many uses of ? operator:

notnull.MaybeNull?.MayAlsoBeNull?.Something ?? DefaultThing

Also consider whether you should be formatting the date for the user using this fixed way, or whether it would make more sense to use their culture's typical date format and present the date in different formats to different site visitors

See something like this or perhaps this for how to make your code use the user's language declaration to provide culture specific formatting for things like dates and numbers

UnassignedReferenceException even though using the null-conditional operator

Unity has a custom way to check inspector's references against null.

When a MonoBehaviour has fields, in the editor only[1], we do not set those fields to “real null”, but to a “fake null” object. Our custom == operator is able to check if something is one of these fake null objects, and behaves accordingly

They may not have overloaded the null-conditional operator. Your get property returns the "fake null" explaining your unassigned error (and not the NullReferenceException).

The custom null check also comes with a bunch of downsides.
It behaves inconsistently with the ?? operator, which also does a null check, but that one does a pure c# null check, and cannot be bypassed to call our custom null check.

I guess the same problem occurs for the null-conditional operator.



Related Topics



Leave a reply



Submit