Julian Herbold
Julian Herbold

Reputation: 537

C# generic constraints : Interface

I got a question for some code:

interface IDistance<T> 
{
        double distance();
        double distance(T obj);
}

class Point<T> where T : IDistance<T>  //why do i need this?
{
        T obj;
        public double dist(T val) { return obj.distance(val); 
        public Point(T obj) { this.obj = obj; }
}

class P2D : IDistance<P2D>
{
        public double[] x = new double[2];

        public P2D(double x, double y)
        {
            this.x[0] = x; this.x[1] = y;
        }

        public double distance()
        {
            double d = 0.0;
            for (int i = 0; i < 2; i++) d = d + x[i] * x[i];
            return Math.Sqrt(d);
        }

        public double distance(P2D val)
        {
           double d = 0.0;
           for (int i = 0; i < 2; i++) d = d + Math.Pow(x[i]-val.x[i],2);
           return Math.Sqrt(d);
        }
}

class Tester
{
        static void Main(string[] args)
        {
            P2D P1 = new P2D(3.0, 4.0);
            Point<P2D> C1 = new Point<P2D>(P1);
            Console.WriteLine(C1.dist());
        }
} 

The code in detail is rather unimportant.

Why do I need the constrain where T : IDistance<T> in the generic class Point<T>?

When I only specify classes that already implemented the interface IDistance<T> like Class P2D, shouldn't be the interface already implemented implicit in the class Point?

I get the fact that it can cause problems, when a class as type <T> in class Point is defined that has not implemented the interface. But in this case, why is it not possible?

Upvotes: 1

Views: 244

Answers (4)

Jon Skeet
Jon Skeet

Reputation: 1503984

Look at this code within Point<T>:

T obj;
public double dist(T val) { return obj.distance(val); 

When the compiler tries to understand what this expression means:

obj.distance(val)

it has to resolve the distance member. If T is unconstrained, it can't do that. When T is constrained to implement IDistance<T>, it can - it resolves it to the member of the interface.

In particular, without the constraint, I could use the type in very odd ways:

Point<string> weird = new Point<string>("foo");
double result = weird.dist("bar");

What would you expect that to do?

(As a side note, it would be worth following normal .NET naming conventions, even for examples. Methods should be PascalCased, and I'd never call a class P2D...)

Upvotes: 2

Felipe Oriani
Felipe Oriani

Reputation: 38638

why do i need this?

You need the constraint because you are restricting the generic type to be an implementation of the interface, IDistance<T>. If Point class you use some methods from this type like obj.distance(val);.

You also could use a abstract class to restrict derivations. Take a look at documentation in MSDN. http://msdn.microsoft.com/en-us/library/bb384067.aspx

Upvotes: 1

Ben Aaronson
Ben Aaronson

Reputation: 6975

When I only specify classes that already implemented the interface IDistance like Class P2D, shouldnt be the interface already implemented implicit in the Class Point? I get the fact that it can cause problems, when a class as type in Class Point is defined that has not implemented the interface. But in this case, why is it not possible?

Because C# is a language that has compile-time type safety. Without that constraint, you may only ever instantiate Point<T> with values of T at run-time which implement IDistance<T>, but there's no way for the compiler to know at compile-time that you will be so well-behaved.

Upvotes: 1

Christos
Christos

Reputation: 53958

class Point<T> where T : IDistance<T>  //why do i need this?

You need this becuase the class you declare, should take as type a type that implements the interface called IDistance<T>

Upvotes: 0

Related Questions