2

I'm learning C# and trying to handle the influx of "a could be null" warnings.

I was wondering, since it's such a common case to error out when something is null, either by returning from the function or throwing an exception, does C# have some kind of syntactical sugar for that case ?

Example of what I have in mind: int a = obtainA() ??? { Console.WriteLine("Fatal error;") return }; (this is not real code)

I know about the ?? and ??= operators, but they don't seem to help much here and I haven't found better.

If not, what would be the closest we have to emulating this ? Is there no better way than to write the following ?

int? nullableA = obtainA();
int a;
if (nullableA.HasValue) {
    a = nullableA.Value;
}
else {
    Console.WriteLine("Fatal error");
    return;
}
/* use a, or skip defining a and trust the static analyzer to notice nullableA is not null */
Julien BERNARD
  • 653
  • 6
  • 17
  • `_a = a ?? throw ArgumentNullException()` is possible – Klaus Gütter Jan 09 '23 at 09:23
  • If you want to throw exception on null, then you can use `??`: `int a = obtainA() ?? throw new Exception(...)` – Evk Jan 09 '23 at 09:23
  • Note also that `Console.WriteLine` followed by `return` is *rarely* the right way to deal with errors and a bad habit to get into. You haven't done what the caller expected you to do and they have no way of finding that out. That's why answers/comments are solely going down the "throw an exception" route. – Damien_The_Unbeliever Jan 09 '23 at 09:36
  • *Side note:* regarding `is null` vs. `== null`, check [this thread](https://stackoverflow.com/questions/40676426/what-is-the-difference-between-x-is-null-and-x-null). Also this does not seem to be what you want as this would try to assign `null` to `a` and throw an exception. You would rather write `if (nullableA.HasValue)` in the code above. – evilmandarine Jan 09 '23 at 09:38

3 Answers3

6

"or_throw" can be achieved with ?? operator since C# 7 using the throw expressions introduced in this language version:

int? i = null;
int j = i ?? throw new Exception();

Another throw approach can be achieved with ArgumentNullException.ThrowIfNull:

#nullable enable
int? i = null;
ArgumentNullException.ThrowIfNull(i);
int j = i.Value; // no warning, compiler determines that i can't be null here

Also you can write your own method supporting nullable flow analysis (like ArgumentNullException.ThrowIfNull does) with attributes for null-state static analysis interpreted by the C# compiler:

#nullable enable
int? i = null;
if (IsNullAndReport(i)) return;
int j = i.Value; // no warning, compiler determines that i can't be null here

bool IsNullAndReport([NotNullWhen(false)]int? v, [CallerArgumentExpression(nameof(i))] string name = "")
{
    if (v is null)
    {
        Console.WriteLine($"{name} is null;");
        return true;
    }

    return false;
}

And pattern matching approach:

int? i = null;
if (i is { } j) // checks if i is not null and assigns value to scoped variable 
{
    // use j which is int
}
else
{
    Console.WriteLine("Fatal error");
    return;
}
Guru Stron
  • 102,774
  • 10
  • 95
  • 132
2

The ?? operator is often used for this, particularly in parameter null tests:


public class A
{
   private readonly string _firstArg;
   private readonly string _secondArg;
   public A(string firstArg, string secondArg)
   {
      _firstArg = firstArg ?? throw new ArgumentNullException(nameof(firstArg));
      _secondArg = secondArg ?? throw new ArgumentNullException(nameof(secondArg));
   }
}

This throws an exception if the passed parameter was null, ensuring that the field values will never be null (and thus not requiring any further null tests anywhere else in the class).

PMF
  • 14,535
  • 3
  • 23
  • 49
1

There is also a static helper method for this: ArgumentNullException.ThrowIfNull():

int? nullableA = null;
ArgumentNullException.ThrowIfNull(nullableA);

This will throw:

ArgumentNullException: Value cannot be null. (Parameter 'nullableA')

It uses the new CallerArgumentExpressionAttribute to auto-magically add the name of the variable in question to the error message.

Good Night Nerd Pride
  • 8,245
  • 4
  • 49
  • 65