﻿# NullReferenceException in C\#\. What is it and how to fix it?

A NullReferenceException \(NRE\) is a type of \.NET exception\. It occurs when a developer tries to dereference a null reference\. This article covers the reasons that lead to exceptions of this type, as well as ways to prevent and fix them\.

![1049_NullReferenceException/image1.png](https://import.viva64.com/docx/blog/1049_NullReferenceException/image1.png)

**Note**\. This article is aimed at beginner programmers\. For developers with experience, I suggest 2 activities:

* check if you know all the ways of encountering the _NullReferenceException_ mentioned here;
* play the [bug\-finding game](https://quiz.pvs-studio.com/en/csharp/)\. 

## What causes a NullReferenceException?

### Theory

Variables of reference types in C\# store references to objects\. To indicate that the reference does not point to an object, the _null_ value is used\. It is also worth noting that _null_ is the default value of reference type expressions\. 

An exception of the _NullReferenceException_ type occurs when you try to dereference a null reference\. Examples of such operations are listed below\. 

Example: 

```cpp
Object notNullRef = new Object();
Object nullRef = default;

int hash;
hash = notNullRef.GetHashCode();
hash = nullRef.GetHashCode(); // NullReferenceException (NRE)
```

The code shows that two variables of the _Object_ reference type are declared — _notNullRef_ and _nullRef_:

* _notNullRef_ stores a non\-null reference\. It refers to the created object;
* _nullRef_ contains the default value of the _Object _type — _null_\. 

![1049_NullReferenceException/image2.png](https://import.viva64.com/docx/blog/1049_NullReferenceException/image2.png)

A call to the _GetHashCode_ method via a reference in _notNullRef_ will work fine, as the reference refers to an object\. An attempt to call the same method on _nullRef_ will result in the CLR throwing a _NullReferenceException_\. 

Below we will look at cases where _null_ values can come from and what operations can lead to a _NullReferenceException_\.   

### How a variable can get a null value

Here are some examples of how a _null_ value can get into a variable\. 

1\. The _null_ or _default_ value is written explicitly\.

```cpp
String name = null;
var len = name.Length; // NRE
```

The result of the _default_ and _default\(T\)_ expression for reference types will also be _null_\.

```cpp
Object obj = default; // or default(Object)
var hash = obj.GetHashCode(); // NRE
```

2\. Initialization of the field of the reference type by default\. 

```cpp
class A 
{
  private String _name;
  public void Foo()
  {
    var len = _name.Length; // NRE
  }
}

var obj = new A();
obj.Foo();
```

In the example, the _\_name_ field is initialized with the default value\. The _\_name_ field is _null_ when _Foo_ is called, so an exception will be thrown when the _Length_ property is accessed\.

3\. The result of the null\-conditional operator's \(?\.\)\.

```cpp
String name = user?.Name;
var len = name.Length; // Potential NRE
```

If the value of _user_ or _user\.Name_ will be _null_, the _null_ value will also be written to the _name_ variable\. In this case, accessing to the _Length_ property without checking for _null_ will lead to an exception\. 

4\. The result of casting with the _as_ operator\. 

```cpp
Object obj = new Object();
String name = obj as String; // unsuccessful cast, name is null
var len = name.Length; // NRE
```

The result of the casting using the _as_ operator will be _null_ if the casting fails\. 

In the example above, the _obj_ variable stores a reference to an instance of the _Object_ type\. An attempt to cast _obj_ to the _String_ type will fail, as a result of which the _null_ value will be written to _name_\. 

5\. The result of the _\*OrDefault_ method's call\. 

Methods of the _\*OrDefault _\(_FirstOrDefault_, _LastOrDefault_, etc\.\) kind from the standard library return the default value if the predicate value does not match any item or the collection is empty\.

```cpp
String[] strArr = ....;
String firstStr = strArr.FirstOrDefault();
var len = firstStr.Length; // Potential NRE
```

If there are no elements in the _strArr _array, the _FirstOrDefault_ method returns the value of _default\(String\)_ — _null_\. When dereferencing a null reference, an exception occurs\.

6\. The boxing of _default_ value of the _Nullable<T\>_ type\. 

The result of boxing _Nullable<T\>_ instances with the _default_ value is _null_\. 

```cpp
long? nullableLong1 = default;
long? nullableLong2 = null;

Nullable<long> nullableLong3 = default;
Nullable<long> nullableLong4 = null;
Nullable<long> nullableLong5 = new Nullable<long>();

var nullableToBox = ....; // nullableLong1 — nullableLong5

object boxedValue = (Object)nullableToBox; // null
_ = boxedValue.GetHashCode(); // NRE
```

If any of the _nullableLong1_ \- _nullableLong5_ values are written to the _nullableToBox_ variable and then boxed, the result will be _null_\. If such a value is used without checking for _null_, an exception will be thrown\. 

The details of boxing _Nullable<T\>_ values are described in the article "[Do you remember nullable value types well?](https://pvs-studio.com/en/blog/posts/csharp/0772/)"\.  

### Null\-value operations that lead to the exception

This section lists operations whose execution with the _null _value results in _NullReferenceException_\. 

1\. Explicit access to a member of an object\. 

```cpp
class A
{
  public String _name;
  public String Name => _name;
  public String GetName() { return _name; }
}

A aObj = null;
_ = aObj._name; // NRE
_ = aObj.Name; // NRE
_ = aObj.GetName(); // NRE
```

The same thing happens when you dereference within a method:

```cpp
void Foo(A obj)
{
  _ = obj.Name; 
}

A aObj = null;
Foo(aObj); // NRE inside method
```

2\. Index access\. 

```cpp
int[] arr = null;
int val = arr[0]; // NRE
```

3\. Calling a delegate\. 

```cpp
Action fooAct = null;
fooAct(); // NRE
```

4\. Iteration in _foreach_\.

```cpp
List<long> list = null;
foreach (var item in list) // NRE
{ .... }
```

Note that the '?\.' operator won't help here:

```cpp
foreach (var item in wrapper?.List) // Potential NRE
{ .... }
```

If _wrapper_ or _wrapper\.List_ is _null_, an exception will still be thrown\. This case is described in more detail in the article "[The ?\. operator in foreach will not protect from NullReferenceException](https://pvs-studio.com/en/blog/posts/csharp/0832/)\."  

5\. The use of the _null_ value as an operand for _await_\. 

```cpp
Task GetPotentialNull()
{
  return _condition ? .... : null;
}
await GetPotentialNull(); // Potential NRE
```

6\. The unboxing of _null_ values\. 

```cpp
object obj = null;
int intVal = (int)obj; // NRE
```

7\. The throwing an exception with a _null_ value\.

```cpp
InvalidOperationException invalidOpException 
  = flag ? new InvalidOperationException() 
         : null;

throw invalidOpException; // Potential NRE
```

A _null_ value can be written to the _invalidOpException_ variable\. In this case, an exception of the _NullReferenceException_ type will be thrown\. 

8\. Dereferencing the _Target_ property of the _WeakReference_ type instance\. 

```cpp
void ProcessIfNecessary(WeakReference weakRef)
{
  if (weakRef.IsAlive)
    (weakRef.Target as DataProcessor).Process(); // Potential NRE
}
```

The reference in the _WeakReference_ points to an object while not protecting it from garbage collection\. If the object is reclaimed for garbage collection after the check of _weakRef\.IsAlive_, but before calling the _Process_ method, then:

* the _weakRef\.Target_ will be _null_;
* the result of the _as_ operator will also be _null_;
* when trying to call the _Process_ method, _NullReferenceException_ will be thrown\.  

9\. The use of the value of the reference type's field before explicit initialization\. 

```cpp
class A
{
  private String _name;
  public A()
  {
    var len = _name.Length; // NRE
  }
}
```

At the time of the _Length_ property dereferencing, the _\_name_ field is initialized with the default value \(_null_\)\. The result of dereferencing is an exception\. 

10\. Unsafe call of event handlers in multithreaded code\.

```cpp
public event EventHandler MyEvent;

void OnMyEvent(EventArgs e)
{
  if (MyEvent != null)
    MyEvent(this, e); // Potential NRE
}
```

If the _MyEvent_ will have no subscribers between the _MyEvent \!\= null_ check and the call of the event's handlers, an exception of the _NullRefernceException_ type will be thrown\.

## How to avoid NullReferenceException

To avoid exceptions of the _NullReferenceException_ type, exclude the situation of null references dereference\. To do this, follow the steps:

* identify where the null reference comes from and how it gets into an expression;
* change the logic of the application so that null reference access does not occur\. 

Example:

```cpp
foreach (var item in potentialNullCollection?.Where(....))
{ .... }
```

If the value of the _potentialNullCollection_ is _null_, the operator '?\.' will also return _null_\. An exception will be thrown when attempting to traverse the collection in the _foreach_ loop\.

If _potentialNullCollection_ in this code fragment is never _null_, it is worth removing the '?\.' operator so as not to confuse developers and code analysis tools:

```cpp
foreach (var item in potentialNullCollection.Where(....))
{ .... }
```

If _potentialNullCollection_ can take the _null_ value, it is worth adding an explicit check or using the '??' operator\.  

```cpp
// 1
if (potentialNullCollection != null)
{
  foreach (var item in potentialNullCollection.Where(....))
  { .... }
}

// 2
foreach (var item in    potentialNullCollection?.Where(....) 
                     ?? Enumerable.Empty<T>)
{ .... }
```

**Note**\. Adding a check for _null _inequality is the easiest way to avoid _NullReferenceException_\. However, sometimes such a fix will not solve the original problem, but only mask it\. So when fixing code, it is useful to think about whether adding a check will be enough or whether something else needs to be fixed in the code\. 

## How to prevent NullReferenceException 

In addition to the fairly obvious tip "do not dereference null references", there are several practices that will help avoid the NRE exceptions\.

### Use the nullable context

Without the nullable context, the _null_ value is considered valid for reference types:

```cpp
String str = null; // No warnings
```

Since C\# 8, the language allows the use of the nullable context\. It introduces the concept of nullable reference types\. In the nullable context, reference types are considered to be those that do not allow _null_ values\. For example, if you use the nullable context on the code we've just looked at, the compiler will issue a warning: 

```cpp
String str = null; // CS8600
```

Warning: _CS8600 Converting null literal or possible null value to non\-nullable type_\.

The situation is the same when calling methods:

```cpp
void ProcessUserName(String userName)
{
  var len = userName.Length;
  ....
}
....
ProcessUserName(null); // CS8625
```

Compiler warning: _CS8625 Cannot convert null literal to non\-nullable reference type_\.

To tell the compiler that a variable of reference type can take the _null_ value, use the '?' symbol:

```cpp
String firstName = null; // CS8600
String? lastName = null; // No warning
```

If you try to dereference a nullable variable without checking for _null_, the compiler will also issue a warning:

```cpp
void ProcessUserName(String? userName)
{
  var len = userName.Length; // CS8602
}
```

Compiler warning:_ CS8602 \- Dereference of a possibly null reference_\.

If you want to tell the compiler that an expression is definitely not _null_ in a particular place in your code, you can use the null\-forgiving operator — '\!'\. Example:

```cpp
void ProcessUserName(String? userName)
{
  int len = default;
  if (_flag)
    len = userName.Length; // CS8602
  else
    len = userName!.Length; // No warnings
}
```

Thus, the nullable context helps to write code in such a way as to minimize the possibility of dereference of null references\.

There are several ways to enable the nullable context:

* change the corresponding option in the project settings \("Nullable" in Visual Studio or "Nullable reference types" in JetBrains Rider\);
* configure the setting in the project file \(\.csproj\) by writing the following: <_Nullable\>enable</Nullable_\>;
* use the _\#nullable enable_ / _\#nullable disable_ directives in the code\.

The nullable context has much more configuration options\. We covered them in more detail in a separate [article](https://pvs-studio.com/en/blog/posts/csharp/1017/)\.

**Note**\. Note that nullable context affects the compiler's warning issuing, but not the application execution logic\.

```cpp
String? str = null;
var len = str!.Length;
```

The compiler will not issue warnings for this code, since the code uses the null\-forgiving operator\. However, at runtime, an exception of the _NullReferenceException_ type will occur here\. 

### Use static analysis

Static analyzers help find security defects and errors in code\. In particular, analyzers help find the places where exceptions of the _NullReferenceException_ type may occur\.

An example of such a static analyzer is [PVS\-Studio](https://pvs-studio.com/en/pvs-studio/)\.

Let's look at the example of C\# code in which a _NullReferenceException_ may occur\.

```cpp
private ImmutableArray<char>
GetExcludedCommitCharacters(ImmutableArray<CompletionItem> items)
{
  var hashSet = new HashSet<char>();
  foreach (var item in items)
  {
    foreach (var rule in item.Rules?.FilterCharacterRules)
    {
      if (rule.Kind == CharacterSetModificationKind.Add)
      {
        foreach (var c in rule.Characters)
        {
          hashSet.Add(c);
        }
      }
    }
  }

  return hashSet.ToImmutableArray();
}
```

In the second _foreach_ loop, developers traverse the _FilterCharacterRules_ collection\. To get the collection, they use the _roslynItem\.Rules?\.FilterCharacterRules_ expression_\. _The '?\.' operator implies that the _Rules_ property may be _null_\. However, if the result of the expression is _null_, a _NullReferenceException_ will still occur when attempting to enumerate the _null_ value in _foreach_\. 

PVS\-Studio finds this problem and issues the [V3153](https://pvs-studio.com/en/docs/warnings/v3153/) warning\.

![1049_NullReferenceException/image3.png](https://import.viva64.com/docx/blog/1049_NullReferenceException/image3.png)

If _items\.Rules_ can indeed have the _null_ value, you can protect the code from _NullReferenceException_ with an additional check:

```cpp
foreach (var item in items)
{
  if (item.Rules == null)
    continue;

  foreach (var rule in item.Rules.FilterCharacterRules)
  {
    ....
  }
}
```

The analyzer will not issue a warning for fixed code\.

PVS\-Studio searches for various situations in code where a _NullReferenceException_ may occur:

* [V3080](https://pvs-studio.com/en/docs/warnings/v3080/)\. Possible null dereference\.
* [V3083](https://pvs-studio.com/en/docs/warnings/v3083/)\. Unsafe invocation of event, NullReferenceException is possible\.
* [V3095](https://pvs-studio.com/en/docs/warnings/v3095/)\. The object was used before it was verified against null\.
* etc\.



<details>
   <summary>How to install and launch PVS\\\-Studio?</summary>

To use PVS\-Studio to check your code, follow the steps:

1. [Get a license key](https://pvs-studio.com/en/pvs-studio/try-free/) \(you will receive it by email\)\. 
1. [Download](https://pvs-studio.com/en/pvs-studio/download/) and install the analyzer\.
1. [Enter the key](https://pvs-studio.com/en/docs/manual/0046/)\. 
1. Check the code\. 



Documentation on working with PVS\-Studio in different environments:

* [Visual Studio](https://pvs-studio.com/en/docs/manual/6522/);
* [JetBrains Rider](https://pvs-studio.com/en/docs/manual/0052/);
* [console](https://pvs-studio.com/en/docs/manual/0035/)\. 




</details>