0

I want to cast an object instantiated from the Activator to a interface with a generic type.

public interface IFoo { }

public interface IBar<T> where T : IFoo {
   void Bal(T item);
}

public abstract class Bar<T> : IBar<T>
  where T : IFoo
{ 
  public abstract void Bal(T item);
}

public class Foo : IFoo
{ }

Now I have a lot of classes like Baz:

public class Baz : Bar<Foo>
{
  public override void Bal(Foo item);
}

I instantiale Baz with the activator.

var instanceOfBaz = Activator.CreateInstance(typeof(Baz));

Now I want to cast Baz back to the base implementation so I can call method Bal from the caller.

public IBar<IFoo> CreateInstanceOfBaz()
{
  var instanceOfBaz = Activator.CreateInstance(typeof(Baz));

  var castedBaz = (IBar<IFoo>) instanceOfBaz;
  var alsoCastedBaz = instanceOfBaz as IBar<IFoo>;

  return castedBaz;
}

But castedBaz will throw a InvalidCastException and alsoCastedBaz is null. So now I can't call the Bal method, nor get the object as IBar<IFoo>. I need this because I have a List of the IBar<IFoo> which I need in another place.

Above code will compile because the relations are valid, but runtime it will fail.

The project is running .NET Framework 4.7.2 and C# 7.

How do I solve my project so I can get the instantiated object as IBar<IFoo>? It is not an option to use reflection to call the Bal method, because I will still need the object in my list.

Roy Berris
  • 1,502
  • 1
  • 17
  • 40
  • 2
    `IBar` is invariant with regard to `T`, so a `Bar` is not a `IBar`. – Johnathan Barclay Dec 03 '21 at 14:34
  • @JohnathanBarclay `IBar` is `IFoo` because that is described in the `where` clause? – Roy Berris Dec 03 '21 at 14:38
  • As Johnathan said, your interface is invariant. And even if you introduced variance, it would have to be contravariance - you could cast `Bar` to `Bar`, but not the other way around. [Covariance and Contravariance in Generics | Microsoft Docs](https://learn.microsoft.com/en-us/dotnet/standard/generics/covariance-and-contravariance) – Richard Deeming Dec 03 '21 at 14:38
  • 1
    `Bar` is *not* an `IBar`. If it was and the cast worked, `castedBaz.Bal(new SomethingIFooButDefinitelyNotFoo())` could be called on that poor `Bar` which isn't expecting to receive anything other than a `Foo`. – Damien_The_Unbeliever Dec 03 '21 at 14:40
  • 1
    `Bar` is an `IBar` but not an `IBar`, and you are trying to cast an instance of `Bar` to `IBar`. – Johnathan Barclay Dec 03 '21 at 14:41
  • `Baz` inherits from `Bar` which implements `IBar`. If it were possible to cast to `IBar` then someone could do that and call `castedBaz.Bal(valueWhichIsIFooButNotFoo)` which is going to cause problems. This is why you can't cast this way round even with covariance, you need contravariance which doesn't help to cast `Bar` to `IBar`, only the other way round – Charlieface Dec 03 '21 at 15:04

0 Answers0