Search code examples
c#casting

Casting an object using the "as" keyword returns null


Here are my class definitions:

public abstract class AbstractEntity : ...
public partial class AbstractContactEntity : AbstractEntity, ...
public sealed class EntityCollectionProxy<T> : IList<T>, System.Collections.IList where T : AbstractEntity

Now I get an object from a delegate, and I want to cast it, but it doesn't work as I expect it to:

EntityCollectionProxy<AbstractContactEntity> obj = resolver.DynamicInvoke (this.entity);
var col = obj as EntityCollectionProxy<AbstractEntity>;

col is null. And if I try the regular casting, var col = (Entity...) obj), I get an exception.

I expected that it would work since the types are coherent. What did I miss?


Solution

  • They are not the same types. It is the same as with List<string> and List<int>: They also can't be casted to one another. That AbstractContactEntity is a AbstractEntity doesn't change this. Extracting an interface from EntityCollectionProxy<T> and making it covariant doesn't work either, because you want to implement IList<T> which means you have input paramaters and return values of type T which prevents covariance.

    The only possible solution is the following:

    var tmp = (EntityCollectionProxy<AbstractContactEntity>)obj;
    var col = tmp.Select(x => (AbstractEntity)x);
    

    col will be of type IEnumerable<AbstractEntity>. If you want to have a EntityCollectionProxy<AbstractEntity>, you need to create a new one:

    var result = new EntityCollectionProxy<AbstractEntity>(col);
    

    This assumes that your EntityCollectionProxy<T> class has a constructor that accepts an IEnumerable<T>.
    But beware, this will be a NEW instance and not the same as returned by resolver.DynamikInvoke.