Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implicitly convert nullable type to non-nullable type

Tags:

c#

.net

I have a nullable c# 10 .net 6 project with an extension method to ThrowIfNull

using System;
using System.Runtime.CompilerServices;

#nullable enable
public static class NullExtensions
{
    public static T ThrowIfNull<T>(
        this T? argument, 
        string? message = default, 
        [CallerArgumentExpression("argument")] string? paramName = default
    )
    {
        if (argument is null)
        {
            throw new ArgumentNullException(paramName, message);
        }
        else
        {
            return argument;
        }
    }
}

The extension method implicitly converts string? to string but it does not work for other primitive types like int? or bool?

public class Program
{
    public static void Main()
    {
        Console.WriteLine("Hello World");
        
        string? foo = "foo";
        string nonNullableFoo = foo.ThrowIfNull();  // success from "string?" to "string"
        Console.WriteLine(nonNullableFoo);
        
        bool? baz = true;
        bool nonNullableBaz = baz.ThrowIfNull();    // success from "string?" to "string"
        Console.WriteLine(nonNullableFoo);
        
        int? bar = 2;
        int nonNullableBar = bar.ThrowIfNull(); // error: Cannot implicitly convert type 'int?' to 'int'
        Console.WriteLine(nonNullableBar);
    }
}

How do I make the extension implicitly convert int? and bool??

Here is the full dotnet fiddle https://dotnetfiddle.net/LiQ8NL

like image 824
Ssh Quack Avatar asked May 13 '26 14:05

Ssh Quack


2 Answers

You can achieve your goal by providing one extension method for non-nullable reference types and another for unmanaged (e.g. int, bool, ...) types. Note that unmanaged types require a cast.

public static class NullExtensions
{
    public static T ThrowIfNull<T>(
        this T? argument,
        string? message = default,
        [CallerArgumentExpression("argument")] string? paramName = default
    ) where T : notnull
    {
        if (argument is null)
        {
            throw new ArgumentNullException(paramName, message);
        }
        else
        {
            return argument;
        }
    }

    public static T ThrowIfNull<T>(
        this T? argument,
        string? message = default,
        [CallerArgumentExpression("argument")] string? paramName = default
    ) where T : unmanaged
    {
        if (argument is null)
        {
            throw new ArgumentNullException(paramName, message);
        }
        else
        {
            return (T)argument;
        }
    }
}

Use like this:

int? foo = 42;
int bar = foo.ThrowIfNull();
Console.WriteLine(bar);

string? baz = "Hello";
string quus = baz.ThrowIfNull();
Console.WriteLine(quus);

// Comment out either this
baz = null;
quus = baz.ThrowIfNull();
// Or this
foo = null;
bar = foo.ThrowIfNull();
like image 140
Eric J. Avatar answered May 15 '26 02:05

Eric J.


Using the null-coalescing Operator ??

To assign a nullable value to a non-null variable, consider the following code:

int? value = 28;
int result = value ?? -1;
Console.WriteLine($"The result is {result}");
  • Output: The result is 28
int? value = null;
int result = value ?? -1;
Console.WriteLine($"The result is {result}");
  • Output: The result is -1

Editing The Code

Rearrange the code as follows. Therefore bool? You can use the type implicitly:

int? bar = 2;
int nonNullableBar = bar ?? -1; 
Console.WriteLine(nonNullableBar);
bool? baz = true;
bool nonNullableBaz = false;
        
if (baz == true){ 
    nonNullableBaz = true;
} 
else if(baz == false){ 
    nonNullableBaz = false;
} 
else {
    /* Something */
}

References
  • Nullable Value Types
  • Boolean Logical Operators
like image 37
Sercan Avatar answered May 15 '26 02:05

Sercan



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!