views:

86

answers:

5

The following code compiles:

class Testing<TKey, TValue>
{
    public bool Test(TKey key)
    {
        return key == null;
    }
}

However, TKey can be a value type, and possibly not allow the value "null".

I know the results of this program, and how to add constraints. What I'm wondering is why doesn't the compiler disallow this when TKey is not constrained to "class"?

+1  A: 

As for the "why", I'm not sure. But to fix it, you can use default(T) instead of null.

Joel Coehoorn
Nope - you can't compare with default(T) using ==. The *only* value you can compare with is null.
Jon Skeet
Well, that depends if that is the purpose of the function.His version...var testing = new Testing<int, object>();bool result = testing.Test(0); // false;Your version...var testing = new Testing<int, object>();bool result = testing.Test(0); // true;
JohannesH
Couldn't you do an assigment to a different variable from default(T), and compare to that?
Joel Coehoorn
You can do assignments, but you can't do comparisons. I suspect that's to discourage people from thinkinh that an overloaded == will be called.
Jon Skeet
You can use Comparer<T>.Default though.
Jon Skeet
Okay, thanks. I thought about deleting this, but I'll leave it up in case someone else has the same confusion.
Joel Coehoorn
+5  A: 

It's convenient to be able to do this in various cases. If TKey is a non-nullable value type, the result of the comparison will always be false. (It's possible that the JITter will remove that branch entirely - don't forget that although one version of the JITted code is shared for all reference types, it reJITs for each value type.)

EDIT: One interesting use for this is precisely to allow Nullable<T> comparisons with null. TFoo=Nullable<T> doesn't satisfy either the where TFoo : class or where TFoo : struct constraints.

Jon Skeet
Since you won't get any notice when I reply to your comment to my answer, I'm posting here as well: couldn't you assign to a different temp variable from default(T) and then compare to that?
Joel Coehoorn
A: 

Because it cast your variable to object and use object == operator For a value type it's always false.

Think Before Coding
A: 

because everything in csharp is an object.
in other words Every type in C# directly or indirectly derives from the object class type.
example

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        struct SimpleStruct
        {
            int a;
            public SimpleStruct(int a)
            {
                this.a = a;
            }
        }
        enum SimpleEnum
        {
            a = 1,
            b = 2,
        }

        static void Main(string[] args)
        {
            SimpleStruct tp = new SimpleStruct(2);

            object ob = tp;
            if (ob != null)
            {
                Console.WriteLine("struct is an object : " + ob);
                tp = (SimpleStruct)ob;
            }

            SimpleEnum tp2 = SimpleEnum.a;
            ob = tp2;
            if (ob != null)
            {
                Console.WriteLine("enum is an object : " + ob);
                tp2 = (SimpleEnum)ob;
            }
            Console.ReadKey();
        }
    }
}
Avram
he said he knows how to add constraints. he's wondering why the compiler will let you write "key == null" WITHOUT the constraint.
Lucas
A: 

Because TKey could be nullable type.

Since C# 2.0 struct is comparable with null. That's why you can write 0 == null with no compile error.

chaowman