Pregunta

I wrote this trivial utility function:

public static T isNull<T>(T? v, T d)
{
    return v == null ? d : v.Value;
}

the purpose is to avoid annoying task like check for a member to be null, very common in reading a linq recordset. The problem is that it's throwing this error:

The type 'T' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method 'System.Nullable< T>'

The error seems legit, anyway I wish I can do something like this:

int? myField = record.myField;
int  myValue = isNull(myField, 0);

instead of:

int? myField = record.myField;
int  myValue = myField == null ? 0 : myField.Value;

I feel like I'm missing some c# basic knowledge. Does exist a way to accomplish my task?

¿Fue útil?

Solución 2

This is called null coalescing, and there is a built in operator to do it:

int myValue = record.myField ?? 0

Otros consejos

Generic constraints can be used on generic functions to limit the types that are permitted to be used to certain subsets, and this opens up possibilities for how you might use those types inside your method or class.

In this case, you can apply a constraint to T that limits it to a struct to resolve your specific compiler error.

public static T IsNull<T>(T? v, T d) where T : struct
{
    return v == null ? d : v.Value;
}

However, another answer does correctly point out that you could opt to use the null coalescing operator ?? in this particular situation.

While the other answers are good, presumably you'd like to write your method so it would work with both reference and value types. You can accomplish that by having two overloads, both with generic constraints.

public static T IsNull<T>(T v, T d) where T : class
{
    return v ?? d;
}

public static T IsNull<T>(T? v, T d) where T : struct
{
    return v.HasValue ? v.Value : d;
}

NOTE: Calling IsNull with a value type other than Nullable<T> will still not compile. e.g.

string myString = ...
Console.WriteLine(IsNull(myString, "foo"))            // works

object myObject = ...
Console.WriteLine(IsNull(myMyObject, new object()))   // works

DateTime? myDateTime = ...
Console.WriteLine(IsNull(myDateTme, DateTme.Now))     // works

int? myInt1 = ...
Console.WriteLine(IsNull(myInt1, DateTme.Now))        // works

int myInt2 = ...
Console.WriteLine(IsNull(myInt2, DateTme.Now))        // <-- compiler error
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top