views:

170

answers:

5

When enforcing a Generic constraint

class GenericTest
{
    public void Sample<T>(T someValue) where T:Racer,new()
    {
        Console.WriteLine(someValue.Car);
    }
}

The Type T should be derived from the Base Type Racer (Correct me if anything wrong).

public class Racer
    {
        string name;
        string car;
        public Racer() { }
        public Racer(string name, string car)
        {
            this.name = name;
            this.car = car;
        }

        public string Name
        {
            get { return name; }
        }
        public string Car
        {
            get { return car; }
        }

    }

In "Main()" I am executing as

static void Main(string[] args)
    {

        List<Racer> rcr = new List<Racer>();
        rcr.Add(new Racer("James","Ferrari"));
        rcr.Add(new Racer("Azar","Bmw"));

        rcr.Sort(delegate(Racer a, Racer b)
        {return a.Name.CompareTo(b.Name); });

        GenericTest tst = new GenericTest();

        tst.Sample<Racer>(rcr[0]);

        Console.ReadLine();

    }

My Question is:

The constraint I implemented is where T:Racer,new(),So T should be derived from Racer. But In Main() I am passing ( tst.Sample<Racer>(rcr[0]);) the type "Racer".The code is working.

How come the Racer be derived from Racer?

+7  A: 

Derived from is the wrong way to read this constraint. It is better read as "is convertible to". This is why Racer works in this scenario.

EDIT : More details

This is covered in section 10.1.5 in the C# language spec. ...

If a constraint is a class type, an interface type, or a type parameter, that type specifies a minimal “base type” that every type argument used for that type parameter must support.

JaredPar
"is convertible to" is not *exactly* the best way to think of it.
Martinho Fernandes
@Martinho, agreed it's not perfect but it's a somewhat simplified way of thinking about it.
JaredPar
+5  A: 

What you are saying with that constraint is that the generic type argument T must be Racer, or a type that descends from Racer, not that it must be a descendant only.

Lasse V. Karlsen
+8  A: 

MSDN: http://msdn.microsoft.com/en-us/library/d5x73970.aspx

where T : <base class name>
The type argument must be or derive from the specified base class.

The point to note is must be or derive from. That means Racer and any class that derives from Racer.

Yogesh
simple and nice.
A: 

The constraint would be true if the object that you are passing in can be cast to the type you've specified on the constraint.

BlueSam
+1  A: 

One way to look at it is "Can an object of type T be assigned to a Racer reference?"

chris