1

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"?

TheSoftwareJedi
  • 34,421
  • 21
  • 109
  • 151

5 Answers5

5

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
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 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 Feb 10 '09 at 18:01
1

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

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • Nope - you can't compare with default(T) using ==. The *only* value you can compare with is null. – Jon Skeet Feb 10 '09 at 17:57
  • Well, that depends if that is the purpose of the function. His version... var testing = new Testing(); bool result = testing.Test(0); // false; Your version... var testing = new Testing(); bool result = testing.Test(0); // true; – JohannesH Feb 10 '09 at 17:58
  • Couldn't you do an assigment to a different variable from default(T), and compare to that? – Joel Coehoorn Feb 10 '09 at 18:00
  • 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 Feb 10 '09 at 18:16
  • You can use Comparer.Default though. – Jon Skeet Feb 10 '09 at 18:17
  • Okay, thanks. I thought about deleting this, but I'll leave it up in case someone else has the same confusion. – Joel Coehoorn Feb 10 '09 at 18:18
0

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

thinkbeforecoding
  • 6,668
  • 1
  • 29
  • 31
0

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
  • 4,267
  • 33
  • 40
  • he said he knows how to add constraints. he's wondering why the compiler will let you write "key == null" WITHOUT the constraint. – Lucas Feb 10 '09 at 18:54
0

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.