views:

68

answers:

2

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?

+7  A: 

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.

Fredrik Mörk
"Reference types are not value types" LOL
Danny Chen
I would also add where T : struct and where T : class constraints to methods.
Andrew Bezzub
Sorry it was a copy/paste mistake for line r3, I'll update the question, "three", "four" should be the parameters.
Sara Gamage
Also thanks, I see it's about understanding "Nullable<T>" now :)
Sara Gamage
@Sara: regarding understanding Nullable<T>, 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
A: 

If you want to achieve this, you need to use non nullable types in your parameters areBothNotNull<T>(T p1, T p2) and check whether T is a Nullable<> in your implementation

If so, use IsNull otherwise, use object.ReferenceEquals (I presume you want to ignore value types like int...)

vc 74