I want to create a simple method that accepts both value type and reference type parameters, i.e. int is value, and string is reference.
So this is what I start with:
public bool AreBothNotNull<T>(T? p1, T? p2)
{
return (p1.HasValue && p2.HasValue);
}
So I want to be able to use it like this:
var r1 = AreBothNotNull<int>(3, 4); // will be true
var r2 = AreBothNotNull<int>(3, null); // will be false
var r3 = AreBothNotNull<string>("three", "four"); // will be true
var r4 = AreBothNotNull<string>(null, "four"); // will be false
But the first issue I encounter is
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'
To proceed I add a struct constraint to my method
public bool AreBothNotNull<T>(T? p1, T? p2) where T : struct
But now the method won't accept the string based calls, and gives me this error:
The type 'string' must be a non-nullable value type in order to use it as parameter 'T' in the generic type or method.
Is this possible? Or why are we prevented from doing this?
Your problem is that you want generic type constraints that are conflicting with each other:
Nullable<T>
works with value types onlySo you will need to have two overloads for your code to work:
public static bool AreBothNotNull<T>(T? p1, T? p2) where T : struct
{
return (p1.HasValue && p2.HasValue);
}
public static bool AreBothNotNull<T>(T p1, T p2)
{
return (p1 != null && p2 != null);
}
Still, the following line will never compile:
var r3 = AreBothNotNull<string>(3, 4);
There is a conflict here, where the generic type argument states that the parameters are of type string
, but the code tries to pass int
s instead.