3

I'm trying to cast a concrete class with generics to its interfaces and getting an error. I'm not sure what I'm missing. I need to get them into the common type.

Unable to cast object of type 'HierarchalLocationFilterSet' to type 'ImAFilterSet`1[ModelBase]'.

Everything compiles and runs, I just cant seem to do something like below.

ImAFilterSet<IModelBase> c = new HierarchalLocationFilterSet()

I can go half way ok

var thisWorks = c as FilterSetBase<LocationModel>;
var thisAlsoWorks = c as ImAFilterSet<LocationModel>;
//This is a hard fail   
var x = ((ImAFilterSet<ModelBase>) c );
var y = ((ImAFilterSet<IModelBase>) c );

Given

public interface ImAFilterSet<C> where C : IModelBase
{
     List<C> Children { get; set; }
}

public abstract class FilterSetBase<C> : ImAFilterSet<C> where C : IModelBase

public class HierarchalLocationFilterSet : FilterSetBase<LocationModel>

public class LocationModel : ModelBase

public abstract class ModelBase : IModelBase

Thanks!

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
William
  • 1,375
  • 12
  • 27
  • See here: http://stackoverflow.com/questions/2184551/difference-between-covariance-contra-variance and also here: http://stackoverflow.com/questions/1724919/understanding-covariance-and-contravariance-in-c-sharp-4-0. – dbc Mar 15 '15 at 00:45

1 Answers1

4

Generic classes/interfaces are invariant by default in .NET. That's why your code fails.

To cast FilterSetBase<T1> to ImAFilterSet<T2> T1 has to be the same T2. Having T1 inherit T2 is not enough.

You can fix that by changing declaration of FilterSetBase<C>:

public abstract class FilterSetBase<C> : ImAFilterSet<IModelBase>
    where C : IModelBase { }

or you can make ImAFilterSet covariant:

public interface ImAFilterSet<out C>
    where C : IModelBase { }

That's only possible when your interface doesn't declare any methods/properties with argument typed as C.

MarcinJuraszek
  • 124,003
  • 15
  • 196
  • 263