Wouter Van Ranst
Wouter Van Ranst

Reputation: 529

C# Generic Interface - Implement generalization for specialized interfaces

Consider the following snippet. How do I correctly implement the public void GiveFood(IAnimal d) part? The compiler wants implementations of the 2 separate member interfaces (ISeaAnimal and ILandAnimal) but they are handled by the IAnimal method.

    interface IAnimal { }
    interface ILandAnimal : IAnimal { }
    interface ISeaAnimal : IAnimal { }


    interface ICaretaker<in T> where T : IAnimal
    {
        void GiveFood(T d);
    }

    interface ISeaAnimalCaretaker<in T> : ICaretaker<T> where T : ISeaAnimal
    {
        void RefreshWater();
    }

    class SuperCaretaker : ISeaAnimalCaretaker<ISeaAnimal>, ICaretaker<IAnimal>
    {
        public void RefreshWater()
        {
            // ...
        }

        public void GiveFood(IAnimal d)
        {
            // ...
        }
        // ---> The below methods are redundant since GiveFood(IAnimal) is implemented, but the compiler wants them still
        //public void GiveFood(ISeaAnimal d)
        //{
        //    throw new NotImplementedException();
        //}
        //public void GiveFood(ILandAnimal d)
        //{
        //    throw new NotImplementedException();
        //}

Upvotes: 1

Views: 161

Answers (2)

Sweeper
Sweeper

Reputation: 271355

How about using an explicit interface implementation? Note that SuperCaretaker implements both ICaretaker<IAnimal> and ICaretaker<ISeaAnimal>:

class SuperCaretaker : ISeaAnimalCaretaker<ISeaAnimal>, ICaretaker<IAnimal>
{
    public void RefreshWater()
    {
        // ...
    }

    public void GiveFood(IAnimal d)
    {
        // ...
    }

    void ICaretaker<ISeaAnimal>.GiveFood(ISeaAnimal d) => GiveFood(d);
}

This way the ISeaAnimal method is hidden, unless you access it using an expression of type ICaretaker<ISeaAnimal> or ISeaAnimalCaretaker<ISeaAnimal>. This also means that you can just call GiveFood(d); in the implementation without causing infinite recursion.

You don't need the GiveFood(ILandAnimal) method, since SuperCaretaker doesn't implement ICaretaker<ILandAnimal>, but if it does (I don't see why you need to though...), you can write another explicit interface implementation.

Upvotes: 2

Andrea Coluzzi
Andrea Coluzzi

Reputation: 39

Remove the ISeaAnimalCaretaker implementation from SuperCaretaker class, so you can handle IAnimal instances.

Like this:

class SuperCaretaker :  ICaretaker<IAnimal>
    {
        public void RefreshWater()
        {
            // ...
        }

        public void GiveFood(IAnimal d)
        {
            // ...
        }

        // You don't need the other method anymore

}

Upvotes: 0

Related Questions