I have a generic interface hierarchy which describes some controllers for other generic types, and I’m having trouble clarifying in my mind why a particular casting scenario is not valid.
Simplified code is as follows;
// 'DTO' interfaces
public interface IBase
{ }
public interface IDerived : IBase
{ }
// 'DTOs'
public class Base : IBase
{ }
public class Derived : Base, IDerived
{ }
// controller interfaces
public interface IBaseController<T> where T : class, IBase
{ }
public interface IDerivedController : IBaseController<IDerived>
{ }
// controllers
public class BaseController<T> : IBaseController<T>
where T : class, IBase
{ }
public class DerivedController : BaseController<IDerived>, IDerivedController
{ }
Now, the situation I’m having trouble with is this;
IDerivedController x = new DerivedController();
bool is1 = x is IDerivedController; // true
bool is2 = x is IBaseController<IDerived>; // true
bool is3 = x is IBaseController<IBase>; // false ???
The final line is where my confusion lies. The controller interfaces associate correctly, and the ‘DTOs’. But not both together… ?
See http://msdn.microsoft.com/en-us/library/dd997386 for info on variant generic interfaces, which is the heart of what you’re asking. You must declare that an
IBaseController<IDerived>can in fact be used as anIBaseController<IBase>in order for it to be used as such.For the reason for this, consider trying to use a
List<string>as anIList<object>vs trying to use anIEnumerable<string>as anIEnumerable<object>. TheIEnumerableconversion is ok because you can use the items asobjects without any problems, but you can’t add anyobjectto aList<string>, because then it would contain something besidesstrings.If you change it to
public interface IBaseController<out T> where T : class, IBase, thenx is IBaseController<IBase>becomestrue. If the compiler complains that you can’t makeTanoutparameter, then you can’t do the conversion you’re looking to do (unless you change the interface to make it compatible).