tags:

views:

181

answers:

5

The interface:
interface IPlay<T> { }

Classes:
class Mp3Player : IPlay<int> { }
class OggPlayer : IPlay<double> { }
class DummyPlayer : IPlay<object> { }

Trying to use :
1. IPlay<object> player = new Mp3Player ();
2. IPlay<int> player2 = new OggPlayer ();

A Big why 1 and 2. usages can not cast?
int to object, or, int to double. It's possible in nongeneric cases. Is there any other method?

+4  A: 

You are trying to perform invalid casts. The Mp3Player is not an IPlay<object>, it is an IPlay<int>. Your OggPlayer is an IPlay<double>, not an IPlay<int>. You can't cast an IPlay<int> to an IPlay<object> or an IPlay<double> to an IPlay<int> like that. They don't inherit from each other, and because they are generic, they are distinct types strongly differentiated from each other.

In C# 4.0 such implicit casts might, and I stress MIGHT, be possible, due to the improved co/contra variance it will have. But generally speaking, such implicit casts across distinct type boundaries are not possible.

jrista
+2  A: 

What you are looking to do is called covariance and this feature will be supported in C# 4 on interface types.

Andrew Hare
+3  A: 

Imagine:

interface IPlay<T>
{
    T GetSomething();
    DoSomething(T value);
}

So, when using:

IPlay<object> player = new Mp3Player();

Then GetSomething() may be type safe, but how about DoSomething(object value)? ... That call cannot guarantee the logic will work on an object, since the player expects ints.

Note that .NET 4 has a mechanism to indicate the variance of an interface, so that you can mark the interface as only using T as return values, in which case at least your first assignment will work.

Note however that regardless, the second (IPlay<int> player2) will not work, because there is no inheritance relationship between double and int. Being able to cast values implicitly is not the same thing as inheritance.

jerryjvl
+1  A: 

Here is a good talk by Anders Hejlsberg from PDC where he describes how co/contravariance will work in C# 4.0 (among other things).

JP Alioto
A: 

There's a common misconception that IPlay<T> generates a common ancestor, which would be IPlay<object>. This might be valuable, but it is not true.

You must generate and name the common ancestor yourself:

interface IPlay {}
interface IPlay<T> : IPlay {}
David B