13

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?

GrantByrne
  • 849
  • 10
  • 21
Sara Gamage
  • 372
  • 1
  • 3
  • 16

1 Answers1

26

Your problem is that you want generic type constraints that are conflicting with each other:

  • Nullable<T> works with value types only
  • Reference types are not value types

So 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 ints instead.

GrantByrne
  • 849
  • 10
  • 21
Fredrik Mörk
  • 155,851
  • 29
  • 291
  • 343
  • I would also add where T : struct and where T : class constraints to methods. – Andrew Bezzub Oct 23 '10 at 08:44
  • 1
    Sorry it was a copy/paste mistake for line r3, I'll update the question, "three", "four" should be the parameters. – Sara Gamage Oct 23 '10 at 10:44
  • @Sara: regarding understanding Nullable, I wrote a blog post about that a while ago: http://softwareblog.alcedo.com/post/2010/02/16/Nullable3cT3e-vs-null.aspx – Fredrik Mörk Oct 23 '10 at 13:45