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
CodePudding user response:
Found one possible option in MS dotnet docs https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters
Constraint "where T : struct" The type argument must be a non-nullable value type
Also according to this answer https://stackoverflow.com/a/8745492/2877168 it is not possible to make this work for string?
and all other value types. So only way is to define two extension methods. Here is the updated version that works for string?
and int?
, bool?
etc
public static class NullExtensions
{
public static T ThrowIfNull<T>(this T? argument, string? message = default, [CallerArgumentExpression("argument")] string? paramName = default)
where T : struct
{
if (argument is null)
throw new ArgumentNullException(paramName, message);
return (T)argument;
}
public static string ThrowIfNull(this string? argument, string? message = default, [CallerArgumentExpression("argument")] string? paramName = default)
{
if (argument is null)
throw new ArgumentNullException(paramName, message);
return argument;
}
}
A working version of this is at https://dotnetfiddle.net/uBX1w6
CodePudding user response:
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();
CodePudding user response:
1. ??
Using the 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
2. Editing The Code
Rearrange the code as follows. The conditional logical operators &&
and ||
don't support bool?
operands. 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 */
}