C# Set Value if Not Null

In C#, there are scenarios where you want to set a value only if it is not null. This is a common requirement when dealing with nullable types or optional parameters. Let's explore how you can achieve this efficiently in C#.

Using Conditional Assignment

One of the simplest ways to set a value if it is not null in C# is to use conditional assignment. This involves checking if the value is null before assigning it. Here's an example:

In the above code snippet, we check if nullableValue is not null. If it is not null, we assign its value to result ; otherwise, we assign the default value.

Using Null-Coalescing Operator

Another approach to set a value if not null in C# is to use the null-coalescing operator ( ?? ). This operator returns the left-hand operand if the operand is not null, otherwise it returns the right-hand operand. Here's an example:

In this code snippet, result will be assigned the value of nullableValue if it is not null; otherwise, it will be assigned the defaultValue .

Setting a value if it is not null is a common operation in C# programming. By using conditional assignment or the null-coalescing operator, you can easily handle such scenarios efficiently. Choose the approach that best suits your code readability and maintainability.

Now you have learned different ways to set a value if not null in C#. Practice these techniques in your own projects to enhance your C# programming skills.

How to Find Child Node by Name in C# XML

Learn how to efficiently locate and access child nodes by name in XML using C# programming language.

🎓 C# Mastery

Enhance your C# skills with these selected articles!

Managing Resources in C# Using IDisposable Interface

Learn how to efficiently handle resources in C# using the IDisposable interface.

Mastering C# Lambda Expressions: Finding Maximum Values

Learn how to use lambda expressions in C# to find the maximum value in a collection efficiently. Explore advanced techniques and best practices.

Understanding Callbacks in C# Programming

Learn what callbacks are in C# and how they are used to handle asynchronous operations efficiently.

How to Get a List from a JToken in C#

Learn how to extract and work with lists from JToken objects in C#.

Understanding the Use of Two Question Marks in C#

Explore the purpose and functionality of the double question marks in C# programming.

Mastering XML Node Selection in C# with Attribute Values

Learn how to efficiently select XML nodes based on attribute values in C# with practical examples and tips.

Mastering Generic Service Contracts in C# WCF

Learn how to utilize generic service contracts in C# WCF for flexible and reusable communication.

How to Open New Window in C# WebView2

Learn how to open a new window in C# using WebView2

How to Create Value Tuples in C#

Learn how to utilize value tuples in C# to store multiple values together efficiently.

Optimizing Performance with C# SemaphoreSlim

Learn how to boost performance using SemaphoreSlim in C# for efficient synchronization.

Null Coalescing Operator in C#: Simplifying Null Checks

The null coalescing operator in C# is a useful tool for checking and assigning default values to variables. It simplifies the process of checking for null values and assigning a default value when necessary. The operator is represented by two question marks (??), and it returns the value of its left-hand operand if it is not null, otherwise it evaluates the right-hand operand and returns its result.

The null coalescing operator is often used in situations where a default value needs to be assigned to a variable if the original value is null. It is a concise way of writing an if-else statement that checks for null values. The operator is especially useful when working with nullable value types, as it eliminates the need for additional null checks.

Developers can also use the null coalescing assignment operator (??=) to assign a value to a variable only if it is null. This operator is a shorthand way of writing an if statement that checks for null values and assigns a default value if necessary. Overall, the null coalescing operator is a powerful tool in C# that simplifies the process of checking for null values and assigning default values to variables.

Table of Contents

Understanding Null Coalescing Operator in C#

The Null Coalescing Operator (??) is a useful operator in C# that allows developers to check for null values in an expression and assign a default value if the value is null. This operator is used to simplify code and make it more concise.

Here, the operator checks if expression1 is null. If it is, then expression2 is assigned to result . If expression1 is not null, then its value is assigned to result .

When used with reference types, the default value is null . For example, if the type is string , the default value is null . In this case, the operator checks if the string is null and assigns a default value if it is.

The Null Coalescing Operator can also be used in combination with the null-conditional operator (?.). This allows developers to check for null values in a chain of expressions. For example:

Here, the operator checks if expression1 is null. If it is, then expression3 is assigned to result . If expression1 is not null, then expression2 is evaluated. If expression2 is null, then expression3 is assigned to result .

In summary, the Null Coalescing Operator is a useful operator in C# that simplifies code and makes it more concise. It allows developers to check for null values in expressions and assign default values if necessary.

Working with Null Coalescing Operator

The null coalescing operator (??) is a useful tool in C# for handling null values. It allows developers to specify a default value to use when a variable is null, without having to write lengthy if-else statements.

In this example, if the value variable is null, the result variable will be assigned the value of 0.

The null coalescing operator can also be used in combination with the null-conditional operator (?.) to simplify code even further. The null-conditional operator allows developers to check if an object is null before accessing one of its properties or methods. When used in combination with the null coalescing operator, it allows for concise and easy-to-read code.

It is important to note that the null coalescing operator only works with nullable value types or reference types. It cannot be used with non-nullable value types like int or double.

Overall, the null coalescing operator is a powerful tool for simplifying code and handling null values in C#. By using it in combination with the null-conditional operator, developers can write concise and easy-to-read code that handles null values gracefully.

Null Coalescing Operator and Types

The null coalescing operator (??) is a C# operator that is used to assign a default value to a variable if the variable is null. It is a shorthand way of writing an if-else statement that checks if a variable is null.

The null coalescing operator can be used with different types of operands, including nullable types and value types. When using the null coalescing operator with nullable types, the operator returns the value of the left-hand operand if it is not null, otherwise it returns the value of the right-hand operand.

When using the null coalescing operator with value types, the operator returns the value of the left-hand operand if it is not equal to the default value of the value type, otherwise it returns the value of the right-hand operand. For example, if the left-hand operand is an integer with a value of 0, and the right-hand operand is an integer with a value of 1, the operator will return 1.

It is important to note that the null coalescing operator cannot be used with non-nullable value types. If a non-nullable value type is used as the left-hand operand, the operator will not compile. However, the operator can be used with nullable value types, which allow the value type to be assigned a null value.

In summary, the null coalescing operator is a useful C# operator that can be used with different types of operands and variables. It allows for concise and readable code that assigns default values to variables when they are null.

Null Coalescing Operator and Extension Methods

The null coalescing operator (??) is a useful tool in C# that allows developers to assign a default value to a variable if it is null. However, the operator only works on simple objects and does not help if developers need to access a member of that object. This is where extension methods come in.

Extension methods allow developers to add functionality to existing classes without having to create a new class or modify the existing one. By using extension methods, developers can extend the functionality of the null coalescing operator to work on more complex objects.

For example, an extension method can be created to handle null values on an IEnumerable collection. This method can be used to return an empty collection instead of a null value, making it easier to work with the collection in subsequent code.

Overall, the combination of the null coalescing operator and extension methods can help developers write more efficient and effective code by handling null values more gracefully.

Null Coalescing Operator in SQL

The SQL Coalesce function returns the first non-null expression among its arguments. It is a useful tool for handling null values in SQL queries. The syntax for the Coalesce function is as follows:

The Null Coalescing Operator (??) in C# is similar to the Coalesce function in SQL. It returns the value of its left-hand operand if it is not null, otherwise, it returns the value of its right-hand operand.

In SQL, the Coalesce function is often used in conjunction with the IsNull function to handle null values. The IsNull function returns the first expression if it is not null, otherwise, it returns the second expression.

The above SQL query will return the value of column1 if it is not null, otherwise, it will return the value of column2.

The Coalesce function can also be used to concatenate strings in SQL. For example, the following SQL query will concatenate the values of column1 and column2, separated by a space.

The above SQL query will return the concatenated value of column1 and column2, separated by a space. If either column1 or column2 is null, it will be replaced by an empty string.

Null Coalescing Operator and Conditional Operators

The null coalescing operator (??) is a useful operator in C# that can be used to provide a default value for a null value. It returns the left-hand operand if it is not null, otherwise, it returns the right-hand operand. This operator can be combined with conditional operators to make code more concise and readable.

The conditional operator (?:) is a ternary operator that evaluates a Boolean expression and returns one of two possible values depending on the result of the evaluation. It is right-associative, meaning that the right operand is evaluated before the left operand. This operator can be used to provide a default value for a null value, but it requires more code than the null coalescing operator.

The throw expression is a new feature in C# 7.0 that allows an exception to be thrown as an expression. This can be useful for providing a default value in case of an error. For example, if a database query fails, the throw expression can be used to return a default value instead of throwing an exception.

The FirstOrDefault method is a LINQ extension method that returns the first element of a sequence or a default value if the sequence is empty. This method can be used in combination with the null coalescing operator to provide a default value for a null value.

The ValueOrDefault method is a method that returns the value of a nullable value type or a default value if the value is null. This method can be used in combination with the null coalescing operator to provide a default value for a null value.

Null Coalescing Operator and Overloading

The null coalescing operator ?? in C# is a shorthand way of checking if a value is null and providing a default value if it is. It is often used to simplify code and make it more concise.

In C#, the null coalescing operator can be overloaded to provide additional functionality. Overloading the null coalescing operator allows the developer to define custom behavior when using the operator with different types of operands.

An example of overloading the null coalescing operator in C# is shown below:

In the example above, the null coalescing operator is overloaded for the int? and int types. The operator returns the value of the left-hand operand if it is not null, otherwise it returns the value of the right-hand operand.

In addition to overloading the null coalescing operator, C# also provides the null-conditional operators ?. and ?[] , which can be used to safely access members of an object or array that may be null.

Overall, the null coalescing operator and overloading can be useful tools for simplifying code and providing custom behavior when working with nullable types in C#.

Related posts:

Leave a comment cancel reply.

DEV Community

DEV Community

waelhabbal

Posted on Jun 13, 2023

The Right Way to Check for Null in C#

One of the most common tasks in C# programming is checking for null values. In fact, it's so common that there are several ways to do it. Some ways are better than others, and some ways can even lead to bugs or performance problems. In this article, we'll explore the right way to check for null in C#.

Before we get started, let's review what null is. Null is a special value that represents the absence of a value. It's often used to indicate that a variable or parameter has not been initialized or assigned a value. If you try to use a null value, you'll get a NullReferenceException.

Now, let's look at some examples of how to check for null in C#.

  • Using the == operator

The most common way to check for null is using the == operator. Here's an example:

This code checks whether the name variable is null using the == operator. If it is null, it prints a message to the console. This method works fine, but it's not the best way to check for null in C#.

The == operator compares the values of two instances. When comparing reference types such as strings, it checks whether the two instances point to the same memory location. If they do, the operator returns true. If they don't, the operator returns false. When comparing a reference type to null, the operator returns true if the reference is null, and false otherwise.

It's worth noting that the == operator can be overridden in C#. This means that if you're working with custom classes or structs, the behavior of the == operator might not be the same as the default behavior. For example, you might want to override the == operator for a custom class to compare the values of two instances of the class, rather than their memory addresses. Here's an example of how to do that:

In this example, we've overridden the == operator for the Person class to compare the Name property of two instances of the class. We've also handled the case where one or both of the instances are null.

  • Using the ReferenceEquals method

The ReferenceEquals method is another way to check for null in C#. Here's an example:

This code checks whether the name variable is null using the ReferenceEquals method. If it is null, it prints a message to the console.

The ReferenceEquals method checks whether two instances refer to the same memory location. If they do, the method returns true. If they don't, the method returns false. This is different from the == operator, which compares the values of two instances.

It's worth noting that the ReferenceEquals method cannot be overridden in C#.

  • Using the is operator

The is operator is another way to check for null in C#. Here's an example:

The is operator checks whether an instance is of a certain type or whether it is null. It returns true if the instance is of the specified type or null, and false otherwise.

When you match an expression against null, the compiler guarantees that no user-overloaded == or != operator is invoked.

  • Using negation pattern (is not null) Note: Beginning with C# 9.0

Here's an example:

This code checks whether the name variable is not null using the ! operator. If it is not null, it prints the value of name to the console. If it is null, it prints a message to the console.

It's worth noting that the ! operator is only available in C# 9.0 and later.

In general, it's a good practice to use the is operator when checking for null, because it explicitly checks for null values without the potential confusion of comparing instance values. However, if you need to compare instance values, you can use the == operator, but be aware that it may give unexpected results if the instances being compared are not of the same reference.

To summarize, the == operator compares the values of two instances, while the ReferenceEquals method checks whether two instances refer to the same memory location. The is operator checks whether an instance is of a certain type or whether it is null. The ! operator is a shorthand way to check for null in C# 9.0 and later. When checking for null, it's generally better to use the is operator, but if you need to compare instance values, use the == operator with caution and be aware of its potential pitfalls. It's also worth noting that the ReferenceEquals method cannot be overridden.

In summary, here's a quick reference guide to the different ways to check for null in C#:

  • Use the is operator to check for null values and whether a reference is of a certain type.
  • Use the == operator to check for null values for value types and to compare the values of two instances. Always test the behavior of overridden operators for custom classes and structs.
  • Use the ReferenceEquals method to check if two instances refer to the same memory location. It should not be used to check for null values.
  • Use the is not null pattern to check for non-null values in C# 9.0 and later.
  • Always use the recommended approach of using the is operator to check for null values to avoid potential issues and confusion.

Top comments (1)

pic

Templates let you quickly answer FAQs or store snippets for re-use.

nawafmahsoun profile image

  • Education dotnet developer
  • Work dotnet developer
  • Joined Jun 2, 2023

thanks for information you'r the best

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink .

Hide child comments as well

For further actions, you may consider blocking this person and/or reporting abuse

samira_talebi_cca34ce28b8 profile image

Newtonsoft.Json vs. System.Text.Json in .NET 8.0: Which Should You Choose?

Samira Talebi - Aug 5

guigovaski profile image

Default interface methods no C#

Guilherme Govaski - Aug 5

sabrina_abcdna123 profile image

.Net versiyalari

Sabrina - Aug 5

hbolajraf profile image

C# | Types of Classes

Hassan BOLAJRAF - Jul 25

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Checking for null in C#, using the null-conditional and null-coalescing operators

Checking for nulls in C# is tedious, but C# 6 gave us the null-conditional and null-coalescing operators. Let's see how they've improved things.

Boy, that's a catchy title. Sometimes they just roll off the tongue, ya know? 🙄

Last week, I wrote about using string interpolation to craft readable strings , and figured it might be worth investigating some of the other useful additions to C# over the last few years. So let's check out new ways (well, new compared to C#'s age) to efficiently check for nulls.

Anyone who's spent some time in C# has had a run in with the dreaded NullReferenceException . The underlying cause isn't always obvious, but getting around it usually is - just check for nulls. Traditionally, the only way to safely use some deeply nested object was to check for null at every level, so a lot of older apps are littered with code like this:

That is just so long-winded and boring. We shouldn't have to type all that repetitive code out, and we don't. C# 6 gave us a couple new tools - the null-conditional and null-coalescing operators.

First, let's define a few nested classes to use for examples, and then a company with a couple departments and employees to experiment with. If you want to play around with the project I created, grab the code on GitHub .

Null Conditional operator

The null-conditional operator allows you to call a deeply-nested class member, where anything in the chain of objects might be null, and it returns null instead of throwing an exception.

In the above code, for example, the Company has a name. But what if it didn't, and you tried to get the length of it for some reason? It would throw an exception if you didn't check for null first. Null conditional operator to the rescue.

By adding a single ? to the second line in the right place, it stores null instead of throwing an exception. One caveat is that, even though Length returns an integer, the variable on the left is actually an int? , since it needs to be able to store null.

Here's another example, where one company has a URL, but the other does not. Since URL is null on the second line, accessing Host would normally throw an exception.

You only have to use them where you're worried about nulls too. If you've defined your classes in such a way that if there's a department, then it will have a collection of employees (maybe an empty one), then you can just use the null conditional operator in the one place you're worried about.

Note #1: The operator always applies to the variable right before it. So above, if Departments is null then you're safe. But if Departments is instantiated but empty, then trying to access the first element from the collection will still throw a different exception.

Note #2: Use these where it makes sense. I happen to think that, if there's no reasonable explanation for a certain variable to ever be null, then it's probably better to let it throw an exception so you can debug it, rather than aggressively preventing NullReferenceException everywhere and giving things default values where it doesn't make sense.

Null Coalescing operator

Using the null coalescing operator with the null conditional gives you even more power, but it's still concise enough for a single line. It lets you define what the default value should be when a value is null. For example, you can replace this:

Or even this:

Revisiting the earlier examples, you can use both together to avoid an exception and to decide what the value should be when it's null...

If you want to count the number of employees, but some departments won't have any, then use the null coalescing operator to just say there's 0 employees.

Here's one more example, where some employees don't have a hire date. Not sure why that would be, but out in space you've got bigger fish to fry than recording every alien who joins the crew. Or something.

And that example from the beginning? It becomes this:

If you found this content useful, and want to learn more about a variety of C# features, check out my GitHub repo , where you'll find links to plenty more blog posts and practical examples!

c# assignment if not null

Related Articles

If/else vs switch/case pattern matching, what are list patterns in c#, what are generic attributes in c# 11.

C#: Different ways to Check for Null

What is the classic way to check if for example a parameter value is null ? If you’ve developed with C# since a while, you might be familiar with this classic syntax:

Since C# version 7 you can use the is keyword for the null check like in the snippet below:

But with C# 7, there’s even a shorter syntax. Discards were also introduced. They are unused and ignored variables that are represented in your code with an underscore (_). In combination with the Null-coalescing operator (??) you can write the null check like this:

That means, the whole method looks just like this:

To be honest, I really like the last approach using the discards, but maybe for some developers it’s too much. I think the is keyword is very clear and readable. It is my favorite.

The is keyword has also the big advantage that it ignores any ==/!= operator overloads on the specific class. It will do a null check, no matter if there’s an operator overload or not. That makes it better than just using ==. You can read more about this in this blog post .

The Is Keyword And the Not Pattern in C# 9.0

With C# 9.0, you can combine the is expression with the logical not pattern, which is powerful if you want to check if an object is NOT null. Before C# 9.0 you had to use the is expression like below to check if an object is not null:

Some developers preferred the following syntax to check if the name is not null:

But the statements above are neither very readable nor easy to understand. That’s why many developers still prefer the classic way:

But since C# 9.0, you can write that not null check like below, and I think that is really readable code:

So, with C# 9.0, you can write your null / not-nulll checks like below, and I think that’s readable:

Happy coding, Thomas

Share this:

  • Click to share on Twitter (Opens in new window)
  • Click to share on Facebook (Opens in new window)

Share this post

' src=

Thomas Claudius Huber

Comments (27)

[…] C#: Different ways to Check for Null (Thomas Claudius Huber) […]

' src=

When you want to check for not-null, you can do..

if (foo != null) if (!(foo is null)) if (foo is object)

I prefer the third because it’s clear and concise and doesn’t involve negation or nested parens.

yes, that’s super cool. I really like “foo is object”, but I guess it’s not as obvious as !(foo is null)

Best would be

if(foo is not null)

But we don’t have that (yet?).

' src=

also if(foo is { })

[…] C#: Different ways to Check for Null – Thomas Claudius Huber […]

' src=

Good use of _ = name ?? throw new ArgumentNullException(nameof(name));

it’s sensible and neat

Thanks Dipo. :)

Yes, it is. I like it too.

' src=

I like the ’is’ variant. Hopefully, with the nullable reference types introduced in C#8 we’ll be able to get rid of null-guards like these. If there is a need to represent the possible abscence of a value I prefer the Option type. I wrote a blog post on this topic that you might find interesting, see https://ericbackhage.net/c/nullable-reference-types-compared-to-the-option-monad/

yes, with nullable reference types we should be able to reduce these null-guards in our code.

Thank you for sharing that blog post, it’s a great read! Thomas

' src=

Unfortunately all NRTs bring to the table are compile-time checks that you are putting your null-guards in :)

Thanks for the post Thomas. A quick update for those coming across this article at a later date.

The new C# 9 patterns will bring ‘is not null’, yay! ( https://github.com/dotnet/csharplang/blob/master/proposals/csharp-9.0/patterns3.md#pattern-combinators ).

But we’ll have to wait and see whether Simplified Null Argument Checking will make it into a release https://github.com/dotnet/csharplang/blob/master/proposals/null-arg-checking.md .

Thank you Ben, the new C# 9 patterns are really a great addition to the language.

' src=

Thanks Thomas. I had the following piece of code that does a null check within a Ternary Expression:

private static string GetAttributeValue(Assembly assembly) where T : Attribute { var type = typeof(T); var attribute = assembly .CustomAttributes .Where(x => x.AttributeType == type) .Select(x => x.ConstructorArguments.FirstOrDefault()) .FirstOrDefault(); return attribute == null ? string.Empty : attribute.Value?.ToString(); }

When I updated this to change the line that was attempting a null check to

return attribute is null ? string.Empty : attribute.Value?.ToString();

The compiler explained to me that I am trying to do a null check against a non-nullable value type. By attempting this, I realized the null check was not necessary after confirming the type System.Reflection.CustomAttributeTypedArgument is a non-nullable struct.

So the offending line can be simplified to

return attribute.Value?.ToString();

And this can be simplified to

return attribute.Value.ToString();

Since System.Reflection.CustomAttributeTypedArgument.Value cannot be null.

Does this seem accurate to you? Point of sharing this is to demonstrate after going through a code base to update null checks, I learned something the code was doing that is not necessary: a null check against a non-nullable value type.

Hey Jamie, yes, your adjustments looks accurate to me. I see a lot of code that does null checks against value types that can not be null. :-) Usually you find these also in the warnings of the compiler.

' src=

You’re welcome! Thank you Avi.

' src=

In C# 9.0 you can also test for not null with an empty property pattern. This is useful when you want to assign the result to a variable `if (GetValue() is { } value)`. (But `is not null value` does not compile).

Interesting. Seems to be a shortcut for if (GetValue() is [variabletype] value)

' src=

OHHHH you need c# 9.0 for the “is not null” keywords to work.

I was wondering why it was giving me weird results on my Unity project.

Thanks for your insight. Cheers

Hi Tony, excactly. C# 9.0 rocks it. :)

' src=

Another interesting way (not null): if (value is { })

Absolutely, that one is great too. :-)

' src=

> The is keyword has also the big advantage that it ignores any ==/!= operator overloads on the specific class. It will do a null check, no matter if there’s an operator overload or not.

Bill Gates once said in an interview that he envied Steve Jobs’ taste for choosing simple solutions. Bill Gates hasn’t been running Microsoft for a long time, and certainly not .NET development. But I see that his followers have inherited the same traits.

' src=

Hi Thanks for the article. When I do this:

Student jewll = new student();

I noticed that jewell is NOT NULL, and since it does not have a value, what does it contain? How could I tell it was never had any of its properties assigned a value since it was created? Thanks.

' src=

ArgumentNullException.ThrowIfNull(validateMe, nameof(validateMe));

' src=

Hi Thanks for the article. I have seen null == name been used too, Is it somehow better than any other cases

That’s OK too, and it’s the original syntax to check for null in C# (and still valid!)

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Spam protection: Sum of 5 + 10 ? *

Notify me of follow-up comments by email.

Notify me of new posts by email.

This site uses Akismet to reduce spam. Learn how your comment data is processed .

Related Posts

C# 12: default parameters in lambda expressions.

In the previous blog posts of this C# 12 series you learned about different C# 12 features: Primary Constructors Collection Expressions Alias Any... read more

C# 12: Alias Any Type

In the previous blog posts of this C# 12 series you learned about different C# 12 features: Primary Constructors Collection Expressions In this... read more

C# 12: Collection Expressions

In the previous blog post you learned about C# 12 primary constructors. In this blog post, you will learn about... read more

C# 12: Primary Constructors

In November 2023, Microsoft released .NET 8.0, and since then you can use C# 12.So, it might be a good... read more

Create a GitHub Action in Visual Studio to Deploy Your .NET Web App automatically to Azure on Every Commit

When building a web application, it can be helpful to deploy your application with the latest features and code changes... read more

C# 11.0: Generic Math, C# Operators and Static Abstract/Virtual Interface Members

In the previous blog posts you learned about different C# 11.0 features: Raw String Literals Generic Attributes In this blog post, let's look... read more

C# 11.0: Generic Attributes

In the previous blog post you learned about C# 11.0 raw string literals. In this blog post, you will learn about another... read more

C# 11.0: Raw String Literals

In November 2022, .NET 7.0 was released, and since then, you can use C# 11.0. In version 11.0, the C# language... read more

C# 10.0: Extended Property Patterns – Use the Dot Token to Access Nested Members

In the previous blog posts you learned about different C# 10.0 features: File-scoped namespaces Global using directives In this blog post, let's look... read more

C# 10.0: Global Using Directives – Make Important Namespaces Available in Your Whole Project

In the previous blog post you learned about C# 10.0 file-scoped namespaces. In this blog post you learn about another C# 10.0... read more

  • .NET Framework
  • C# Data Types
  • C# Keywords
  • C# Decision Making
  • C# Delegates
  • C# Constructors
  • C# ArrayList
  • C# Indexers
  • C# Interface
  • C# Multithreading
  • C# Exception

Null-Coalescing Assignment Operator in C# 8.0

C# 8.0 has introduced a new operator that is known as a Null-coalescing assignment operator( ??= ). This operator is used to assign the value of its right-hand operand to its left-hand operand, only if the value of the left-hand operand is null. If the left-hand operand evaluates to non-null, then this operator does not evaluate its right-hand operand.

Here, p is the left and q is the right operand of ??= operator. If the value of p is null, then ??= operator assigns the value of q in p. Or if the value of p is non-null, then it does not evaluate q.

Important Points:

  • The left-hand operand of the ??= operator must be a variable, or a property, or an indexer element.
  • It is right-associative.
  • You cannot overload ??= operator.
                   
         
     
         

author

Please Login to comment...

Similar reads.

  • Best Twitch Extensions for 2024: Top Tools for Viewers and Streamers
  • Discord Emojis List 2024: Copy and Paste
  • Best Adblockers for Twitch TV: Enjoy Ad-Free Streaming in 2024
  • PS4 vs. PS5: Which PlayStation Should You Buy in 2024?
  • 15 Most Important Aptitude Topics For Placements [2024]

Improve your Coding Skills with Practice

 alt=

What kind of Experience do you want to share?

Null-Coalescing Assignment Operator in C#

Back to: C#.NET Tutorials For Beginners and Professionals

Null-Coalescing Assignment Operator in C# 8

In this article, I am going to discuss Null-Coalescing Assignment Operator in C# 8 with Examples. Please read our previous article where we discussed Indices and Ranges in C# 8 with Examples. C# 8.0 has introduced a new operator that is known as a Null-Coalescing Assignment Operator (??=).

Null-Coalescing Assignment Operator (??=) in C# 8

C# 8.0 introduces the null-coalescing assignment operator ??= . We can use this ??= operator to assign the value of its right-hand operand to its left-hand operand only if the left-hand operand evaluates to null. That means the null-coalescing assignment operator ??= assigns a variable only if it is null. The syntax is given below.

Here, a is the left and b is the right operand of the null-coalescing operator ??=. If the value of a is null, then the ??= operator assigns the value of b in a. If the value of a is not-null, then it does not evaluate b.

It simplifies a common coding pattern where a variable is assigned with a value if it is null. For a better understanding, please have a look at the below diagram. Here, you can observe before C# 8, how we are checking null and assigning a value if it is null and how we can achieve the same in C# 8 using the null-coalescing assignment (??=) operator.

Points to Remember While working with ??= in C#:

Null-coalescing assignment operator example in c#:, real-time use cases of null-coalescing assignment operator.

With the help of Null-Coalescing Assignment ??= Operator, we can remove many redundant if-else statements and make our code more readable and understandable. Let us understand this with an example. Here, first, I will show you an example using the if statement, and then I will convert the same example using Null-Coalescing Assignment ??= Operator so that you will get a better idea.

Example using If Statements:

Same example using null-coalescing assignment = operator:.

About the Author: Pranaya Rout

Leave a Reply Cancel reply

How to Handle Null References in the Latest Version of C#

freeCodeCamp

By Zoran Horvat

C# 12 has just been released, and it continues the long tradition of improvements in the safety of the language's software design and execution.

One of these improvements relates to manipulating null references, a programming concept that many developers don't really love.

Using null references in your code can cause all kinds of issues, like exceptions and a lack of information.

This article will teach you how to cope with null references in the latest version of the C# programming language and .NET. The name of the game: let no null pass unattended.

This demonstration will have several stages, each with its own small demo. If you wish to skip through, please use the table of contents below.

Table of Contents

Prerequisites, how to use nullable reference types, how to use the is null and is not null patterns, how to use type-test-and-set patterns, how to use property patterns, how to use the null propagation and null coalescing operators.

  • How to Work with Optional Objects

Final Notes

There are a few prerequisites you will need to meet before proceeding. I assume that you've written enough C# code to see null references in their natural habitat. And I expect you to understand that they can threaten the code's design and stability.

This article will clarify these concepts and identify the issues and solutions using C# syntax and libraries.

If you are ready, we can get started with nullable reference types. That will allow us to set up the working environment and get up to speed for the more complex demos that will follow.

Nullable reference types were introduced in C# 8 and quickly became a mainstay.

The short story is that you can either declare a reference nullable (for example, string? s ) or non-nullable ( string s ).

Note the plot twist: what used to be just a reference before C# 8 ( string s was an ordinary reference to a nullable string) has now become something more: a reference that should never be set to null.

That was the breaking change, maybe the first in a decade of C# syntax evolution!

The compiler will do its best to check if all the assignments to a non-nullable reference (the one without the question mark) set it to a proper object. If it finds an execution path that might set it to null, the compiler will issue a compile-time warning. This is called "definite assignment analysis," as the compiler tries to prove that each non-nullable reference is definitely assigned to an object.

If you have already grown accustomed to nullable reference types, I have a question: would you consider not using them today? Probably not.

Let's start with some code. Below, you see two records – one deriving from another. Record types came with C# 9. I am using them here only for brevity. Consider these two types as just the base and the derived class.

We can either instantiate a record and assign the instance to a reference, or assign a reference to null.

This is where the definite assignment analysis comes to the table. If there is a sequence of instructions in which the reference ends up being null, we must use the question mark to indicate that the reference can be null.

You can see that the second reference ( bob ) is assigned to a proper object but is still declared nullable. That is perfectly fine in scenarios where an object is coming from the outside, and you might not know whether it will be there or not.

Make sure you don't assign a nullable reference to a non-nullable one, though. That would cause a compile-time warning, which you can raise to the level of compile-time error if you prefer.

It is essential to understand that nullability is not the property of the type but rather a hint given to the compiler. Nullable reference types are only used during the compile-time analysis and are never stored in the compiled type itself.

One consequence is that you cannot declare a nullable type parameter in a generic type. That wouldn't make sense because the compiler has no place to put that information in the compiled type!

But then comes a twist because we are free to indicate any reference of the generic parameter type as nullable, as in the code below. Such a reference is subject to definitive assignment analysis as any other.

We have defined the utility function to showcase all situations incorporating null references in the rest of this article. As I already pointed out, it would be a compile-time error to declare this generic function as Showcase<T?> , while accepting a nullable T? in the argument list would be perfectly valid. Makes your head spin around!

An even greater mystery is to come: why not remove nullable from the argument list? What would that mean?

That would leave it to the caller to determine nullability because – now pay attention! – a concrete generic parameter type can be nullable. It determines the nullability of references, which is a real thing during compilation.

I hope you have started to grasp these concepts more now. Unfortunately, it would take a lot of space to explain this concept in-depth, but I would certainly advise you to learn more about nullability of types. It is now part of C# and is here to stay.

Let me give you a quick demo showcasing the two possible choices:

The first call above allows null references in the arguments, while the second call forces non-nullable references. So the compiler would check the references passed as arguments in that case and raise a warning if any of them is, or could be, null.

That concludes our crash course on nullable reference types in C#. We are ready to proceed with more advanced matters.

Before that, here is the output produced by the code as we have it so far:

Pay attention to the empty line in the output. That is where we have passed null to the Console.WriteLine . The WriteLine method accepts null and treats it the same way it treats an empty string.

Once we get nullability right, we can start doing logic around it. The simplest of all operations is asking if a reference is equal to null.

The is operator is testing an object against a pattern. We'll meet this operator several more times in the upcoming sections.

In this demo, you can see its simplest use: testing against the null pattern. There are two possibilities there, is null and is not null , with the meaning that appears to require no further explanation. Oh, but that would be a big mistake!

A corner case is covered by is null and is not null patterns, which might be the core reason for introducing these patterns in the first place. Both patterns will avoid calling any overload of the == and != operators.

So, in theory, a class could overload the == and != operators and, in doing so, declare that a particular object should be considered equal to a null reference. But the is null pattern will not call the operator overload – thus, it will flatly reject comparing that same non-null object to null.

That is a minor corner case, but it teaches how C# operates under the hood. The bottom line is: you should favor is null over == , and is not null over != when testing for null/non-null.

Here is the printout produced when we run the function above on a few references, one of them being null.

The time has come to raise the bar and use some of the more complex methods of processing nullable references. We will remain with the is operator, but this time, we'll use its more potent form: testing type patterns.

Each reference in C# resolves into an object (or a lack of – a null), and each object we reference possesses the type descriptor. That is at the core of any object-oriented language.

So it's pretty easy for the .NET runtime to check whether a reference is pointing to an object – and, if so, whether that object's runtime type derives from a specific type, directly or indirectly.

That was a mouthful, wasn't it? Let's split that up into bits:

  • To test whether a reference references an actual object, that is the person is not null pattern.
  • To add the test whether that object is assignable to a particular type, we use the type pattern instead: person is Celebrity .
  • Finally, to capture the reference to the desired type and use it in subsequent statements and expressions, we use the full-blown type-test-and-set expression: person is Celebrity celeb .

These are the three stages of extracting information from a reference, each more potent than the other.

Without further ado, here is the method that exercises the most detailed form: testing against null and downcasting, all packed in one condensed expression:

You may have noticed that these expressions are effectively implementing safe downcasting. Downcasting was frowned upon for decades, accused (mostly rightfully) of causing code defects and design flaws.

But times they are a-changin'! Type test and set expressions are coming to software development from functional programming.

This article is not a place to discuss the differences between type testing and downcasting as we knew it in object-oriented languages of the past. I strongly encourage you to learn more about this intriguing topic before judging.

Here, you can see the output produced by the function above. As you can see, each actual type is captured correctly, creating its specific output. And the dreaded null was left out – I have indeed passed a null reference to the function at one instant but hadn't matched any of the patterns, and so was ignored.

This demo would be incomplete without one crucial note. The switch expression (of C# 8) is expecting patterns in order from more specific to more general ones. It would be an error to list a more specific pattern after a more general one. The general pattern would overshadow the subsequent one, never letting its right hand execute. Therefore, the switch expression like the one below causes a compile-time error in C#.

An exciting development follows if you push pattern matching even further. One specific form is the properties pattern – one aimed to match the values and attributes of properties of an object (if the object exists!).

You don't have to specify the type if you are not interested in downcasting. It will be the type of the reference to the left of the is operator.

But using the is operator implies a null test. Any reference passing the is test will be non-null and safe to check its property values on the right-hand side of the expression.

Therefore, we read this if instruction's condition as follows: If person is not null, and its property FirstName has a value Bob, then...

Here is the output produced when we call the function above:

So far, we have been doing things to objects, which is awkward in an object-oriented design. Remember, in object-oriented programming, it is the object that exposes behavior, and, as the object's users, we only make calls to its methods.

The problems still come when the reference we expect to point to an object is nullable. Making an unguarded call on the null reference was the primary source of defects. But now, with nullable references and definite assignment checks done for us, we should be safe from the dreaded NullReferenceExceptions .

Consider having a method exposed by the class. We can use ToString as a simple example.

There is a substantial difference between calling ToString on Person and on Person? types. The latter one is nullable, and therefore an unguarded call might cause dereferencing a null reference, leading to a dreaded NullReferenceException , as you can imagine.

Enter the null-propagation operator ( ?. )! We can safely make an optional call to a method, provided the reference is non-null.

But observe the consequences. If the method returns void , the call will be ignored on a null reference. If the method returns a type, then the result will be the nullable version of that type. You cannot expect a string from ToString on a nullable reference, you see? The compiler can only promise a nullable string instead.

And what if we really wanted a string, a true one? Enter the null-coalescing operator ( ?? )! We can easily convert a nullable reference to a non-nullable one by supplying a default to take when the actual value is null at run time.

In this example, we make an optional call to the ToString method first but then short-circuit the result to an empty string if the reference were null. The result is that any null reference would produce an empty string for printout.

How to Work With Optional Objects

The last method of addressing nulls in this article will actually not use nulls. Another riddle! The idea is to avoid nulls altogether by modeling the objects as possibly missing. Mind the word "possibly" – that will become part of the type declaration the same way nullability was.

If you are new to optional objects, then this short explanation will be anything but sufficient to learn about them. C# has no native support for optional objects. You can choose one of the many implementations available on NuGet, the most popular one being the LanguageExt library.

An optional object of some type is an object that either exists or does not exist. Whichever the case, the optional object itself will always exist. Another riddle for you to solve!

Here is how we would declare a few optional objects:

The two shapes of an optional object are usually referred to as None and Some . The Some variant must contain an actual object. That completes the creation of optional objects and the code that will never have a null reference.

But what is the difference compared to nullable references? Why should we use optional objects at all?

The short story is that optional objects let us apply functions to the optional object's content – if present. The optional object will either invoke the function and pass the content to it or skip calling it altogether if there is no content.

Therefore, an optional type is a single place where that calling protocol is now implemented, the protocol in many ways equivalent to safely dereferencing nullable references.

The Match method covers both possibilities: It either maps the Person object to a string or substitutes an empty string if the person is missing. The Do method will only pass content to the console if content exists.

Here is the printout produced by the Do method:

You will only see the Some variants printed out. The only missing object in the input array has produced no output because that optional instance has ignored the action passed to its Do method.

The most significant benefit of using optional objects over nullable references is their ability to apply other functions. We might already have many different classes and methods implemented in our codebase, all methods working on non-nullable references. Optional objects can bridge the gap between potentially missing objects and the common methods that are only operational when nothing is missing.

In this tutorial, we started by declaring nullable objects and testing their existence using the is operator.

Then, we extended the example by displaying the richness of pattern-matching expressions: type test and set and property pattern expressions.

We then moved the focus from consuming objects to calling their behavior from the null-propagation operator over the null-coalescing operator, landing in the vast field of functional programming and optional objects.

I hope you enjoyed the ride. In place of farewell, I will invite you to learn more about optional objects in C# by watching my recent video How to Avoid Null Reference Exceptions: Optional Objects in C# .[

Learn to code. Build projects. Earn certifications—All for free.

If you read this far, thank the author to show them you care. Say Thanks

Learn to code for free. freeCodeCamp's open source curriculum has helped more than 40,000 people get jobs as developers. Get started

  • Essential C#
  • Announcements

As described in Chapter 3, while null can be a useful value, it also comes with a few challenges—namely, the need to check a value isn’t null before invoking the object’s member or changing the value from null to something more appropriate to the circumstance.

Although you can check for null using the equality operators and even the relational equality operators, there are several other ways to do so, including C# 7.0’s support for is null and C# 10.0’s support for is not null . In addition, several operators are designed exclusively for working with the potential of a null value. These include the null-coalescing operator (and C# 8.0’s null-coalescing assignment) and the null-conditional operator. There is even an operator to tell the compiler when you believe a value isn’t null even if it isn’t obvious to the compiler—the null-forgiving operator. Let’s start by simply checking whether a value is null or not.

It turns out there are multiple ways to check for null , as shown in Table 4.4 . For each listing, assume a declaration of string? uriString precedes it:

string ? uriString = null ;

Description

Example

is null Operator Pattern Matching

The is operator provides multiple approaches to check for null. Starting with C# 7.0, you can check whether a value is null using the is null expression. This is a succinct and clear approach to checking if a value is null.

// 1.

if (uriString is null)

{

     Console.WriteLine(

         "Uri is null");

}

is not null Operator Pattern Matching

Similarly, in C# 9.0, is not null support was added. And, when checking for not null, this is the preferred approach.

// 2.

if (uriString is not null)

{

     Console.WriteLine(

         "Uri is not null");

}

Equality/Inequality

Using the equality and inequality operators works with all versions of C#.

In addition, checking for null this way is readable.

The only disadvantage of this approach is that it is possible to override the equality/inequality operator, potentially introducing minor performance impacts.

// 3.

if(uriString == null)

{

     Console.WriteLine(

         "Uri is null");

}

if(uriString != null)

{

     Console.WriteLine(

         $"Uri is: { uriString }");

}

is object

Since C# 1.0, is object checks whether the operand is null, although this syntax isn’t as clear as is not null.

is object is preferable over the is {} expression described in the next row because it issues a warning when the operand is a non-nullable value type. What is the point in checking for null if the operand can’t be null?

// 4.

int number = 0;

if( (uriString is object )

     // Warning CS0183: The given

     // expression is always not

     // null.

     && (number is object)

)

{

     Console.WriteLine(

         $"Uri is: { uriString }");

}

is { } Operator Pattern Matching

The property pattern matching expression, <operand> is { }, (which was added in C# 8.0) provides virtually the same functionality as is object. Besides being less readable, the only noticeable disadvantage is that is {} with a value type expression doesn’t issue a warning, while is object does. And, since a value type cannot be null, the warning is preferable because there is no point in checking a non-nullable value for null. Therefore, favor using is object over is { },

// 5.

if (uriString is {})

{

     Console.WriteLine(

         $"Uri is: { uriString }");

}

ReferenceEquals()

While object.ReferenceEquals() is a somewhat long syntax for such a simple operation, like equality/inequality it works with all versions of C# and has the advantage of not allowing overriding; thus, it always executes what the name states.

// 6.

if(ReferenceEquals(

   uriString, null))

{

     Console.WriteLine(

         "Uri is null");

}

Of course, having multiple ways to check whether a value is null raises the question as to which one to use. C# 7.0’s enhanced is null and C# 9.0’s is not null syntax are preferable if you are using a modern version of C#.

Obviously, if you are programming with C# 6.0 or earlier, the equality/inequality operators are the only option aside from using is object to check for not null . The latter has a slight advantage since it is not possible to change the definition of the is object expression and (albeit unlikely) introduce a minor performance hit. This renders is {} effectively obsolete. Using ReferenceEquals() is rare, but it does allow comparison of values that are of unknown data types, which is helpful when implementing a custom version of the equality operator (see “ Operator Overloading ” in Chapter 10).

Several of the rows in Table 4.4 leverage pattern matching, a concept covered in more detail in the “ Pattern Matching ” section of Chapter 7.

The null-coalescing operator is a concise way to express “If this value is null , then use this other value.” It has the following form:

expression1 ?? expression2

The null-coalescing operator also uses a form of short-circuiting. If expression1 is not null , its value is the result of the operation and the other expression is not evaluated. If expression1 does evaluate to null , the value of expression2 is the result of the operator. Unlike the conditional operator, the null-coalescing operator is a binary operator.

Listing 4.37 illustrates the use of the null-coalescing operator.

In this listing, we use the null-coalescing operator to set fileName to "config.json" if GetFileName() is null . If GetFileName() is not null , fileName is simply assigned the value of GetFileName() .

The null-coalescing operator “chains” nicely. For example, an expression of the form x ?? y ?? z results in x if x is not null ; otherwise, it results in y if y is not null ; otherwise, it results in z . That is, it goes from left to right and picks out the first non- null expression, or uses the last expression if all the previous expressions were null . The assignment of directory in Listing 4.37 provides an example.

C# 8.0 provides a combination of the null-coalescing operator and the assignment operator with the addition of the null-coalescing assignment operator . With this operator, you can evaluate if the left-hand side is null and assign the value on the righthand side if it is. Listing 4.37 uses this operator when assigning fullName .

In recognition of the frequency of the pattern of checking for null before invoking a member, you can use the ?. operator, known as the null-conditional operator , 4 as shown in Listing 4.38 . 5

The null-conditional operator example ( int? length = segments?.Length ) checks whether the operand (the segments in Listing 4.38 ) is null prior to invoking the method or property (in this case, Length ). The logically equivalent explicit code would be the following (although in the original syntax, the value of segments is evaluated only once):

int ? length =

     (segments != null ) ? (int?)segments.Length : null

An important thing to note about the null-conditional operator is that it always produces a nullable value. In this example, even though the string.Length member produces a non-nullable int , invoking Length with the null-conditional operator produces a nullable int ( int? ).

You can also use the null-conditional operator with the array accessor. For example, uriString = segments?[0] produces the first element of the segments array if the segments array was not null . Using the array accessor version of the null-conditional operator is relatively rare, however, as it is only useful when you don’t know whether the operand is null , but you do know the number of elements, or at least whether a particular element exists.

What makes the null-conditional operator especially convenient is that it can be chained (with and without more null-coalescing operators). For example, in the following code, both ToLower() and StartWith() will be invoked only if both segments and segments[0] are not null :

segments?[0]?.ToLower().StartsWith( "file:" );

In this example, of course, we assume that the elements in segments could potentially be null , so the declaration (assuming C# 8.0) would more accurately have been

string ?[]? segments;

The segments array is nullable, in other words, and each of its elements is a nullable string.

When null-conditional expressions are chained, if the first operand is null , the expression evaluation is short-circuited, and no further invocation within the expression call chain will occur. You can also chain a null-coalescing operator at the end of the expression so that if the operand is null , you can specify which default value to use:

string uriString = segments?[0]?.ToLower().StartsWith(

     "file:" ) ?? "intellitect.com" ;

Notice that the data type resulting from the null-coalescing operator is not nullable (assuming the right-hand side of the operator [ "intellitect.com" in this example] is not null —which would make little sense).

Be careful, however, that you don’t unintentionally neglect additional null values. Consider, for example, what would happen if ToLower() (hypothetically, in this case) returned null . In this scenario, a NullReferenceException would occur upon invocation of StartsWith() . This doesn’t mean you must use a chain of null-conditional operators, but rather that you should be intentional about the logic. In this example, because ToLower() can never be null , no additional null-conditional operator is necessary.

Although perhaps a little peculiar (in comparison to other operator behavior), the return of a nullable value type is produced only at the end of the call chain. Consequently, calling the dot ( . ) operator on Length allows invocation of only int (not int? ) members. However, encapsulating segments?.Length in parentheses—thereby forcing the int? result via parentheses operator precedence—will invoke the int? return and make the Nullable<T> specific members ( HasValue and Value ) available. In other words, segments?.Length.Value won’t compile because int (the data type returned by Length ) doesn’t have a member called Value . However, changing the order of precedence using (segments?.Length).Value will resolve the compiler error because the return of (segments?.Length) is int? , so the Value property is available.

Notice that the Join() invocation of Listing 4.38 includes an exclamation point after segments :

uriString = string .Join( '/' , segments ! );

At this point in the code, segments?.Length is assigned to the length variable, and since the if statement verifies that length is not null , we know that segments can’t be null either.

int ? length = segments?.Length;

if (length is not null && length != 0){ }

However, the compiler doesn’t have the capability to make the same determination. And, since Join() requires a non-nullable string array, it issues a warning when passing an unmodified segments variable whose declaration was nullable. To avoid the warning, we can add the null-forgiving operator ( ! ), starting in C# 8.0. It declares to the compiler that we, as the programmer, know better, and that the segments variable is not null . Then, at compile time, the compiler assumes we know better and dismisses the warning (although the runtime still checks that our assertion is not null at execution time).

Note that while the null-conditional operator checks that segments isn’t null, it doesn’t check how many elements there are or check that each element isn’t null.

In Chapter 1 we encountered warning CS8600, “Converting null literal or possible null value to non-nullable type,” when assigning Console.ReadLine() to a string . The occurs because Console.ReadLine() returns a string? rather than a non-nullable string . In reality, Console.ReadLine() returns null only if the input is redirected, which isn’t a use case we are expecting in these intro programs, but the compiler doesn’t know that. To avoid the warning, we could use the null-forgiving operator on the Console.ReadLine() return—stating we know better that the value returned won’t be null (and if it is, we are comfortable throwing a null-reference exception).

string text = Console.ReadLine() ! ;

The null-conditional operator is a great feature on its own. However, using it in combination with a delegate invocation resolves a C# pain point that has existed since C# 1.0. Notice in Listing 4.39 how the PropertyChanged event handler is assigned to a local copy ( propertyChanged ) before we check the value for null and finally fire the event. This is the easiest thread-safe way to invoke events without running the risk that an event unsubscribe will occur between the time when the check for null occurs and the time when the event is fired. Unfortunately, this approach is nonintuitive, and frequently developers neglect to follow this pattern—with the result of throwing inconsistent NullReferenceExceptions . Fortunately, with the introduction of the null-conditional operator, this issue has been resolved.

The check for a delegate value changes from what is shown in Listing 4.39 to simply

PropertyChanged?.Invoke(propertyChanged(

   this , new PropertyChangedEventArgs(nameof(Age)));

Because an event is just a delegate, the same pattern of invoking a delegate via the null-conditional operator and an Invoke() is always possible.

________________________________________

  • p.key == item.key) && !currentPage.some(p => p.level > item.level), }" > p.key == item.key) && !currentPage.some(p => p.level > item.level), }" :href="item.href"> Introduction
  • p.key == item.key) && !currentPage.some(p => p.level > item.level), }" > p.key == item.key), }" :href="item.href"> {{item.title}}

Working With Null in C#

As software developers, we are bound to encounter scenarios where our code behaves in unexpected ways. some of those unexpected behaviors could be caused by null object references. in this post, we're going to take a look at the different language constructs that c# provides for working with null. my goal is to provide information that leads to more tidy code and fewer bugs..

Aaron Bos | Monday, November 29, 2021

Null Basics in C#

Before we get too deep into handling null in our code, let's touch on the basics of null in C#. First, we use the null keyword to represent a null reference (a reference that doesn't refer to any object). A bit later in this post, we'll touch on how null comes into play with different C# types.

One of the main reasons why null can be difficult to work with is the NullReferenceException . This exception is thrown when our code tries to access a member of an object whose value is null . Often times null reference exceptions will occur unexpectedly and can indicate a bug in our code. For example, if we expand on our previous code snippet we'll see a System.NullReferenceException when trying to access the Length property on nullRef .

More often than not null reference exceptions will occur when a method returns null or an object is never instantiated. Null reference exceptions can be very frustrating when they occur unexpectedly, luckily C# has a lot of functionality built into the language that can help us steer clear of these null reference scenarios. The first language feature that we're going to look at is "Nullable Reference Types".

Nullable Reference Types

" Nullable Reference Types " is a feature that was added to C# in version 8.0, but has not been enabled in the language by default until the release of .NET 6 . If using a version of .NET prior to .NET 6 (and still using a language version >= 8.0), nullable reference types will have to be enabled explicitly. The goal of nullable reference types is to minimize the occurrence of null reference exceptions. Let's take a closer look at this feature to see how we can leverage it in our code.

As mentioned previously, nullable reference types are not enabled by default in versions of .NET before .NET 6. There are a few ways to enable the feature which can impact different scopes of our applications. The first option to enable nullable reference types is in the .csproj file and impacts the entire project. Including the line below in the project file will enable nullable reference types for the entire project.

If enabling nullable reference types for the entire project is not possible or ideal, then we can enable the feature using "directives" that are scoped to specific areas of the code. The directive to use is #nullable combined with an option like enable , disable , etc. For more information about the use of directives to control nullable reference types, check out the docs here . Now that we know how to enable nullable reference types in our code, let's see how they work and what they can do for us.

Before C# 8.0 and nullable reference types, all reference types were nullable . The introduction of nullable reference types provides some additional compile-time code analysis along with annotations to explicitly indicate the purpose behind our code. While using nullable reference types we are provided with null-state analysis, which analyzes our code to indicate whether an object reference may or may not be null. The null-state analysis emits warnings to indicate that dereferencing an object (aka accessing an object member) may result in a NullReferenceException . The null-state analysis is able to determine that an object reference is not null OR maybe null based on our code. When a variable is in a maybe null state, then the compiler will emit a warning to indicate that we should check for null before dereferencing the object.

A couple of examples of the warnings we may see after enabling nullable reference types are:

So far we discussed how the compiler analyzes our code to determine whether or not a NullReferenceException is possible based on null-state analysis. Let's take a look at the variable annotations that we can use to indicate to the compiler that a value can be null and mitigate those error messages.

In order to indicate that a particular variable or class member can be null a ? is appended to the end of the type declaration. As mentioned previously, enabling nullable reference types basically means that we are assuming that any reference types in our code should never be null. The ? suffix on the type declaration explicitly indicates that a reference for this object may be null .

It is important to note that appending the ? to the reference type declarations is not the same as the System.Nullable<T> value types. Declaring a null reference type of string? is still using the same underlying type of String, whereas declaring int? is declared using Nullable<int> versus the value type of int . I like to think of nullable reference types as more of a feature of the compiler, while nullable value types are built into the actual runtime.

When we know a reference is not null, but the compiler still emits a warning we can use the "null-forgiving operator" ! to override the warning. This feature should be used only when needed because when using nullable reference types, the goal is for the compiler to help us by indicating when a NullReferenceException is possible.

Nullable reference types are a pretty new feature in C# and may not be widely used at this point, but I really think enabling the feature can improve the quality of our code in many different ways. Next, we'll take a look at operators that will help when assigning values that may be null.

Null-Coalescing and Variable Assignment

In this section, we'll be talking about a couple of operators that help with null checking and value assignment. First, we'll be looking at the null-coalescing operator which was initially introduced in C# 6. The null-coalescing operator is defined by using ?? characters between operands like a ?? b . The purpose of this operator is to return the value of the left operand if it does not evaluate to null. If the left side is null, then the right side of ?? will be evaluated. This operator is very useful for avoiding ternary operators that check for null or for throwing an exception when a value evaluates to null.

Starting with C# 8 the only constraint on the left operand of the null-coalescing operator is that it cannot be a non-nullable value type. Previously the left side of ?? was constrained to a reference type or nullable value type.

Let's take the null-coalescing a bit further by looking at the null-coalescing assignment operator ??= , which was introduced in C# 8. This operator assigns the value of the right operand only if the left operand evaluates to null. Where this may be useful in our code is when we have null checks that assign a variable if it is null.

Both of these null-coalescing features can help tidy up our code and remove explicit null conditions. We have one more feature that can be used in conjunction with null-coalescing operators that will make our lives even easier when dealing with null references.

Null-conditional Operators

The null-coalescing operators were useful for providing a "fallback" so to speak when one side of the operator was evaluated to null. Null-conditional operators also provide some safety in the event of a null operand but will return null if the left side of the operator evaluates to null. There are two null-conditional operators that apply to two operations, member access and element access. The member access operation is defined by ?. and is used when accessing object members (properties, methods, fields, etc.). The element access operation is defined by ?[] and is used when accessing elements of a collection that support access by index.

In the examples above if records or password evaluate to null then the entire expression will evaluate to null and operations to the right of the ? will not be evaluated. The nice thing about the null-conditional operations is that they short-circuit. So the first access operation evaluating to null will short circuit the expression and subsequent operations will not be evaluated. The example with records?[0].Name showcases the short circuit behavior. If records is null , then the access of the Name property will not be evaluated.

I mentioned that the null-conditional operators play well with the null-coalescing operators. The null-conditional operators provide safety around accessing members or elements when null is a possibility. The null-coalescing operator can provide a fallback value if the null-conditional short circuits.

In this post, we've discussed a handful of features provided by C# that make dealing with null a bit easier. Be sure to stay up to date with language versions and features as C# is an ever-evolving language and many of these features have been introduced within the last few releases.

Null-coalescing Operators

This browser is no longer supported.

Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.

! (null-forgiving) operator (C# reference)

  • 7 contributors

The unary postfix ! operator is the null-forgiving, or null-suppression, operator. In an enabled nullable annotation context , you use the null-forgiving operator to suppress all nullable warnings for the preceding expression. The unary prefix ! operator is the logical negation operator . The null-forgiving operator has no effect at run time. It only affects the compiler's static flow analysis by changing the null state of the expression. At run time, expression x! evaluates to the result of the underlying expression x .

For more information about the nullable reference types feature, see Nullable reference types .

One of the use cases of the null-forgiving operator is in testing the argument validation logic. For example, consider the following class:

Using the MSTest test framework , you can create the following test for the validation logic in the constructor:

Without the null-forgiving operator, the compiler generates the following warning for the preceding code: Warning CS8625: Cannot convert null literal to non-nullable reference type . By using the null-forgiving operator, you inform the compiler that passing null is expected and shouldn't be warned about.

You can also use the null-forgiving operator when you definitely know that an expression can't be null but the compiler doesn't manage to recognize that. In the following example, if the IsValid method returns true , its argument isn't null and you can safely dereference it:

Without the null-forgiving operator, the compiler generates the following warning for the p.Name code: Warning CS8602: Dereference of a possibly null reference .

If you can modify the IsValid method, you can use the NotNullWhen attribute to inform the compiler that an argument of the IsValid method can't be null when the method returns true :

In the preceding example, you don't need to use the null-forgiving operator because the compiler has enough information to find out that p can't be null inside the if statement. For more information about the attributes that allow you to provide additional information about the null state of a variable, see Upgrade APIs with attributes to define null expectations .

C# language specification

For more information, see The null-forgiving operator section of the draft of the nullable reference types specification .

  • Remove unnecessary suppression operator (style rule IDE0080)
  • C# operators and expressions
  • Tutorial: Design with nullable reference types

Additional resources

  • Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
  • Advertising & Talent Reach devs & technologists worldwide about your product, service or employer brand
  • OverflowAI GenAI features for Teams
  • OverflowAPI Train & fine-tune LLMs
  • Labs The future of collective knowledge sharing
  • About the company Visit the blog

Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Get early access and see previews of new features.

Why an Out Parameter can be left unassigned in .NET 6 but not .NET 8 (CS0177)?

The same code compiles in a .NET 6 project but shows the compile error CS0177 in .NET 8 - why?

It seems like the rule would only be valid for .net8 or some rules have changed.

Since it seems to work in .NET 6...

The app runs in .NET 6 with the output:

So clearly it uses the default value of the struct. But somehow this is not anymore the case for .NET 8 (I didn't find this documented so far, at least not here )

I tested it with creating 2 new console projects in VS for each version, and also by changing the target framework in both projects with the same result.

CS0177 The out parameter 'parameter' must be assigned to before control leaves the current method     (does not mention versions)

( Why an Out Parameter can be left unassigned in projects targeting .NET Standard? this did not help at all, it talks only about structs not .net versions)

Screenshot VS

  • 4 This is probably a bug in .NET 6, but I can't find the corresponding issue for it –  canton7 Commented Aug 28 at 9:34
  • Interestingly, I get an error on .NET 6 if I replace the DateOnly with a DateTime –  canton7 Commented Aug 28 at 9:36
  • 1 Alternately it could be a bug in C#12 (for .NET 8): if the linked Q re. structs is correct as DateOnly has no accessible instance fields. –  Richard Commented Aug 28 at 9:39
  • @Richard I can't repro on .NET 6 with my own struct which has no accessible instance fields: dotnetfiddle.net/IzoE02 –  canton7 Commented Aug 28 at 9:42
  • @Sinatr It's an instance member in DateOnly as well. static wouldn't be representative –  canton7 Commented Aug 28 at 9:51

2 Answers 2

This is a problem with the reference assemblies in .NET 6. It was fixed in .NET 7.

In C#, a struct is considered "definitely assigned" if it has no fields, see this answer for details.

In .NET 6, the reference assembly for System.Runtime contained a definition for DateOnly and TimeOnly which did not have any fields . The compiler therefore treated it as an empty struct, which didn't need to be explicitly assigned.

See this GitHub issue and this other one for details. This was originally spotted on SO, in this question . It was fixed by changing the tooling which generates the reference assemblies, to include a dummy field in such structs where necessary.

Git claims that the issue was fixed in this commit , but it's not showing up in the diff. I suspect that there's an evil merge in there somewhere which is hiding it.

canton7's user avatar

  • 2 I think you can remove the word "accessible" - I believe this is one of those occasions where the compiler looks under the bonnet - IIRC a lot of the ref assemblies have things like private readonly bool dummy; - edit: looks like different waves of the "fix" for this had different behaviours - "accessible" was relevant for bullet 1 here, but is not any longer now that the missing fields are (mostly) added, I believe: github.com/dotnet/roslyn/issues/29319#issuecomment-414517139 –  Marc Gravell Commented Aug 28 at 10:07
  • @MarcGravell Yep good point thanks, removed –  canton7 Commented Aug 28 at 10:11
  • Isn't this a bug in the compiler that was fixed by changing the reference assembly generation rules, instead of a problem with the reference assemblies themselves? Here it says that even if there is a field in the struct, if that field is of reference type, in another assembly, and private, then the compiler ignores it anyway. –  palapapa Commented Aug 28 at 21:04
  • 1 @palapapa Interesting coincidence. DateOnly/TimeOnly don't have a field which is a reference type, so I don't think that applies here? It is also a fact that the reference assemblies were wrong in .NET 6 and didn't contain any fields at all (there's a link in my answer), and the compiler was following the spec when presented with a type with no fields –  canton7 Commented Aug 29 at 4:52
  • Linked issue github.com/dotnet/runtime/issues/27012 suggests adding <Features>Strict</Features> to your project file as a workaround in .net 6. –  Jeremy Lakeman Commented Sep 5 at 3:52

Working through the latest available C# standard (for C# 8, I don't think anything significant has changed specification-wise for out parameters).

  • 15.6.2.3.4 Output parameters
Within a method, just like a local variable, an output parameter is initially considered unassigned and shall be definitely assigned before its value is used. Every output parameter of a method shall be definitely assigned before the method returns.

As expected out parameters must be assigned (so much it is said twice in the same paragraph).

  • 9.4.1 [Definite assignment | ] General
The definite-assignment states of instance variables of a struct_type variable are tracked individually as well as collectively. In additional to the rules described in §9.4.2, §9.4.3, and §9.4.4, the following rules apply to struct_type variables and their instance variables: An instance variable is considered definitely assigned if its containing struct_type variable is considered definitely assigned. A struct_type variable is considered definitely assigned if each of its instance variables is considered definitely assigned.

Unlike the referenced Q there is nothing here that talks about "accessible fields": they all need to be "definitely assigned".

Because in some cases the SDK has "façade" assemblies which are different to the runtime (eg. DateOnly is documented to be in System.Runtime but is implemented in System.Private.CoreLib ). Sometimes (like DateTime ) the documented assembly forwards to the real implementation and thus is resolved by the compiler enforcing this rule. In other cases (and thus has changed over time as an implementation detail) the façade is only resolved by the loader and JIT compiler at runtime and thus the compiler does not see the internals of the type and cannot see there are fields to be assigned.

For obvious performance in the loader/JIT, and definitely for AoT, the case where the façade forwards is likely to be more common now than in the past.

TL/DR: needing the explicit assignment seems to be correct for any struct with any fields accessible or not (and why, for structs, internal changes can be a breaking changes).

Richard's user avatar

  • 1 Forwarded assemblies aren't relevant to compile-time I think? The compiler relies on reference assemblies only. So "facade" assemblies can't be relevant to this. And I'm not sure how the JIT / AOT is relevant here either. The problem is a compile-time error in one .NET version but not the others. The stuff about "accessible fields" is from "A struct_type variable is considered definitely assigned if each of its instance variables is considered definitely assigned" -- therefore a struct with no fields is always assigned. That, combined with a ref assembly which had no fields, lead to this bug –  canton7 Commented Aug 28 at 11:02
  • @canton7 to convert into native machine code the "real" implementation (not some reference sufficient for compilation to IL) is needed. This will be the JIT compiler at runtime, or when doing an AoT compile. –  Richard Commented Aug 28 at 11:24
  • 2 I know. This error is a compiler error -- it's raised by the compiler at compile-time. The JIT is not the one raising the error. Therefore anything related to the JIT, or types in assemblies resolved at runtime, is not, and cannot, be relevant to the question. –  canton7 Commented Aug 28 at 11:29

Your Answer

Reminder: Answers generated by artificial intelligence tools are not allowed on Stack Overflow. Learn more

Sign up or log in

Post as a guest.

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy .

Not the answer you're looking for? Browse other questions tagged c# .net-6.0 .net-8.0 or ask your own question .

  • The Overflow Blog
  • The hidden cost of speed
  • The creator of Jenkins discusses CI/CD and balancing business with open source
  • Featured on Meta
  • Announcing a change to the data-dump process
  • Bringing clarity to status tag usage on meta sites
  • What does a new user need in a homepage experience on Stack Overflow?
  • Feedback requested: How do you use tag hover descriptions for curating and do...
  • Staging Ground Reviewer Motivation

Hot Network Questions

  • How can we know how good a TRNG is?
  • Romeo & Juliet laws and age of consent laws
  • Simulate Minecraft Redstone | Where to start?
  • How to simplify input to a table with many columns?
  • Is reading sheet music difficult?
  • How to add a line of text at the bottom of the table of contents page?
  • Why does the guardian who admits guilt pay more than when his guilt is established by witnesses?
  • Textile Innovations of Pachyderms: Clothing Type
  • Can anyone debunk this claim regarding Non Hindus and other religion as per Hindu scriptures
  • What was IBM VS/PC?
  • Size of the functor category
  • What are the most common types of FOD (Foreign Object Debris)?
  • Beatles reference in parody story from the 1980s
  • Can the planet Neptune be seen from Earth with binoculars?
  • Are fuel efficiency charts available for mainstream engines?
  • What qualifies as a Cantor diagonal argument?
  • I want to be a observational astronomer, but have no idea where to start
  • Understanding the parabolic state of a quantum particle in the infinite square well
  • Where is this railroad track as seen in Rocky II during the training montage?
  • Sum[] function not computing the sum
  • The head of a screw is missing on one side of the spigot outdoor
  • Is the 2024 Ukrainian invasion of the Kursk region the first time since WW2 Russia was invaded?
  • Using NDSolve to solve the PDEs and their reduced ODEs yields inconsistent results
  • Is there a way to prove ownership of church land?

c# assignment if not null

IMAGES

  1. Null-Coalescing Assignment Operator (??=) in C#

    c# assignment if not null

  2. C# : Add to Collection if Not Null

    c# assignment if not null

  3. C# 23: Check if a string is not null or empty using the IsNullOrEmpty method

    c# assignment if not null

  4. C# Null

    c# assignment if not null

  5. Null-Coalescing Assignment Operator ??=

    c# assignment if not null

  6. How to Assign an Empty Value When String is Null in C#.NET

    c# assignment if not null

VIDEO

  1. Understanding ??= Null Coalescing Assignment Operator

  2. Nested if else statement in C programming

  3. C Assignment multiplication operator #short #c#assignment #multiplication #operator #printf #coding

  4. Dynamic Dispatch

  5. Best way to do null check in C#

  6. Hiç Birşey Bilmeden C#

COMMENTS

  1. c#

    Shortest way to check for null and assign another value if not

  2. ?? and ??= operators

    and ??= operators - null-coalescing operators - C# reference

  3. C# Set Value if Not Null

    In C#, there are scenarios where you want to set a value only if it is not null. This is a common requirement when dealing with nullable types or optional parameters. Let's explore how you can achieve this efficiently in C#. Using Conditional Assignment. One of the simplest ways to set a value if it is not null in C# is to use conditional ...

  4. Null Coalescing Operator in C#: Simplifying Null Checks

    If expression1 is not null, then expression2 is evaluated. If expression2 is null, then expression3 is assigned to result. In summary, the Null Coalescing Operator is a useful operator in C# that simplifies code and makes it more concise. It allows developers to check for null values in expressions and assign default values if necessary.

  5. Null Operators and Handling Null Values in C#

    C# provides three operators to make it easier to work with nulls: the null-coalescing operator, the null-coalescing assignment operator, and the null-conditional operator. Null-Coalescing Operator

  6. The Right Way to Check for Null in C#

    The Right Way to Check for Null in C# - ...

  7. Checking for null in C#, using the null-conditional and null-coalescing

    Checking for null in C#, using the null-conditional and ...

  8. C#: Different ways to Check for Null

    C#: Different ways to Check for Null

  9. Null-Coalescing Assignment Operator in C# 8.0

    In C#, ?? operator is known as Null-coalescing operator. It will return the value of its left-hand operand if it is not null. If it is null, then it will evaluate the right-hand operand and returns its result. Or if the left-hand operand evaluates to non-null, then it does not evaluate its right-hand operand. Syntax: p ?? q Here, p is the left and

  10. c#

    C# 6.0 Null Propagation Operator & Property Assignment (3 answers) Closed 4 years ago . Being a fan of null-coalescing operator and the null-propagating operator, I would like to assign something if the object is not null.

  11. Member access and null-conditional operators and expressions:

    Member access operators and expressions - C#

  12. Null-Coalescing Assignment Operator in C#

    Here, in this article, I try to explain Null-Coalescing Assignment in C# 8 with Examples. I hope you enjoy this Null-Coalescing Assignment in C# with Examples article. Dot Net Tutorials. About the Author: Pranaya Rout. Pranaya Rout has published more than 3,000 articles in his 11-year career. Pranaya Rout has very good experience with Microsoft ...

  13. How to Handle Null References in the Latest Version of C#

    How to Handle Null References in the Latest Version of C#

  14. Essential C#: Programming with null

    These include the null-coalescing operator (and C# 8.0's null-coalescing assignment) and the null-conditional operator. There is even an operator to tell the compiler when you believe a value isn't null even if it isn't obvious to the compiler—the null-forgiving operator. Let's start by simply checking whether a value is null or not.

  15. Attributes for null-state static analysis interpreted by the C# compiler

    Attributes interpreted by the compiler: Nullable static analysis

  16. Method call if not null in C#

    Method call if not null in C# - Stack ...

  17. Working With Null in C#

    Null Basics in C#. Before we get too deep into handling null in our code, let's touch on the basics of null in C#. First, we use the null keyword to represent a null reference (a reference that doesn't refer to any object). A bit later in this post, we'll touch on how null comes into play with different C# types.

  18. C# Null Coalescing (??) operator

    The null coalescing operator (??) in C# is a convenient way to handle null values in expressions. It checks whether its left-hand operand is null and, if so, evaluates and returns the right-hand…

  19. c#

    2. I've been using C# for a long time, and as far as I know, the answer is no. The two options you have are: 1.) Using an if check to short-circuit the logic and skip it if it's not necessary. This should be the fastest to execute, on average. 2.) Using the ternary operator to check and assign in one line.

  20. Nullable types: better way to check for null or zero in c#

    Nullable types: better way to check for null or zero in c# - ...

  21. ! (null-forgiving) operator

    (null-forgiving) operator - C# reference

  22. c#

    This is a problem with the reference assemblies in .NET 6. It was fixed in .NET 7. In C#, a struct is considered "definitely assigned" if it has no fields, see this answer for details.. In .NET 6, the reference assembly for System.Runtime contained a definition for DateOnly and TimeOnly which did not have any fields.The compiler therefore treated it as an empty struct, which didn't need to be ...