5

to avoid confusion I summarised some code:

namespace ConsoleApplication1
{
    class Program
    {
        static void Main()
        {
            IManager<ISpecificEntity> specificManager = new SpecificEntityManager();
            IManager<IIdentifier> manager = (IManager<IIdentifier>) specificManager;
            manager.DoStuffWith(new SpecificEntity());
        }
    }

    internal interface IIdentifier
    {
    }

    internal interface ISpecificEntity : IIdentifier
    {
    }

    internal class SpecificEntity : ISpecificEntity
    {
    }

    internal interface IManager<TIdentifier> where TIdentifier : IIdentifier
    {
        void DoStuffWith(TIdentifier entity);
    }

    internal class SpecificEntityManager : IManager<ISpecificEntity>
    {
        public void DoStuffWith(ISpecificEntity specificEntity)
        {
        }
    }
}

When I debug the code I get an InvalidCastException in Main().

I know that ISpecificEntity implements IIdentifier. But obviously a direct cast from an IManager<ISpecificEntity> into an IManager<IIdentifier> does not work.

I thought working with covariance could do the trick but changing IManager<TIdentifier> into IManager<in TIdentifier> does not help either.

So, is there a way do cast specificManager into an IManager<IIdentifier>?

Thanks and all the best.

Palama
  • 53
  • 4
  • please read: http://stackoverflow.com/questions/245607/how-is-generic-covariance-contra-variance-implemented-in-c-sharp-4-0 – Dave Bish Apr 18 '12 at 14:09

2 Answers2

7

With IManager<IIdentifier> you can do such thing:

IIdentifier entity = new NotSpecificEntity();
manager.DoStuffWith(entity);

That will lead to exception, in your SpecificEntityManager, because it accepts only parameters of type ISpecificEntity

UPDATE: You can read more about covariance and contravariance in C# at Eric Lippert's blog

Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459
  • ... and that's why it isn't allowed to do what the OP wants to do. +1 – Daniel Hilgarth Apr 18 '12 at 14:13
  • But `ISpecificEntity` implements `IIdentifier`. And `TIdentifier` in `IManager` accepts only `IIdentifier`. So, there should not be an exception in that line. Am I wrong? – Palama Apr 18 '12 at 14:32
  • Hmmm. You are right. I think I have to change my summarised code. It does not fit to the problem in the original code. – Palama Apr 18 '12 at 15:04
2

Why not:

ISpecificEntity bankAccountManager = new SpecificEntity();
IManager<IIdentifier> manager = (IManager<IIdentifier>)bankAccountManager;
manager.DoStuffWith(new SpecificEntity());

?

Omar
  • 16,329
  • 10
  • 48
  • 66