tags:

views:

48

answers:

2

This doesn't seem to work. Is it possible?

public interface IInterface1 {}
public interface IInterface2 { }

public interface IMyT1 : IInterface1 {}
public interface IMyT2 : IInterface2 {}

public abstract class BaseClass<T1, T2> : Interface2 where T1 : IInterface1, where T2 : IInterface2
{
     protected T1 T1Obj {get;set;}

     public static explicit operator T1(BaseClass<T1,T2> val)
     {
          return val.T1Obj;
     }
}

public class SomeClass : BaseClass<IMyT1, IMyT2>, ISomeClass {}

Any casts to SomeClass fail with an InvalidCastException.

ISomeClass mySomeClass = new SomeClass();
var myT1 = (IMyT1)mySomeClass; //Boom!

It may be crazy but is it possible?

+3  A: 

What you're looking for is generic variance. At least, I assume so - your example code is missing bits that we'd require in order to check that it would actually work.

You can't use it at all in C# 3 and earlier. In C# 4 you can use it for interfaces and delegates, but only where explicitly marked using in and out appropriately on the type parameters - the compiler makes sure it's all safe, basically.

If you search for generic variance or covariance and contravariance on this site, you'll find plenty of information. Or you could look at Eric Lippert's blog series on it. I give details of it in chapter 13 of C# in Depth and if you search for "covariance" on the NDC 2010 streaming video site you can stream or download an hour-long talk I gave on the topic.

Jon Skeet
Dang. I think you've answered a generic variance question of mine in the past. I didn't even think of it as the issue until you brought this up. I can see why this won't work. Thanks!
Adam Driscoll
Jon, I have your book, C# in Depth (in MEAP, I'm still waiting for the bound edition), and I am very grateful to you for it. It is widening my education in C# like nothing ever before.
Cyberherbalist
@Cyberherbalist: I'm very glad to hear it :) (I'm looking forward to hard copy of the 2nd edition coming out too!)
Jon Skeet
A: 

You object is not of type IMyT1 and that is why the conversion fails.

These are your valid conversions...

var instance = new SomeClass();
var localInterface = (ISomeClass)instance;
var baseClass = (BaseClass<IMyT1, IMyT2>)instance;
var baseInterface = (IInterface2)instance;

... the instance is not of type IMyT1, IMyT2, or IInterface1. Trying to cast to any of those will fail. If BaseClass or SomeClass inherited from IMyT1 then you would be able to complete this conversion.

Also static Methods are resolve at compile time while the cast is considered at RunTime. This is one of the same reasons you can not have virtual static methods.

Matthew Whited