David David - 4 months ago 38
C# Question

Polymorphism, inheritance and generic C# : Cannot cast subclass into supertype

I have a problem with abstract class and generic in c# (I usually code in Java) : here is the code I would like to use :

public interface InterfaceResult {...}

public abstract class Result : InterfaceResult {...}
public class ResultA : Result {...}
public class ResultB : Result {...}

public interface InterfaceKing { InterfaceResult function();}

public abstract class King : InterfaceKing {
public abstract Result function();
}
public class KingA : King {
public override ResultA function(){...}
}
public class KingB : King {
public override ResultB function(){...}
}


but that doesn t work : Visual Studio want for KingA and KingB to return an instance of Result with function(). If i use "new" instead of override, VS say I don t implement the required method (i need to use override).

So I tried with generic and it s not better

public abstract class Result { }
public class ResultA : Result { }
public class ResultB : Result { }

public interface IKing<T> {T function(); }

public abstract class King<Result> : IKing<Result>
{
public abstract Result function();

public static implicit operator King<Result>(KingB v)
{
return v; // generate StackOverflow Exception
}

public static implicit operator King<Result>(KingA v)
{
throw new NotImplementedException();
}
}

public class KingA : King<ResultA>
{
public override ResultA Get()
{
return new ResultA();
}
}

public class KingB : King<ResultB>
{
public override ResultB Get()
{
return new ResultB();
}
}

public class Test
{
King<Result> a = new KingA(); // allowed by public static implicit operator King<Result>(KingA v)
King<Result> b = new KingB(); // allowed by public static implicit operator King<Result>(KingB v)
KingA ka = new KingA();
List<King<Result>> lista = new List<King<Result>>();
public void test()
{
lista.Add(ka);
}
}


How can i make this work ? I can t find any solution nor any good or complete example.

Answer

Moving from "full interface" to "no interface" (for lack of better terms) all that work (this Main works fine)

static void Main ()
{
    King a = new KingA ();
    King b = new KingB ();
    KingA ka = new KingA ();
    List<King> list = new List<King> ();

    list.Add (a);
    list.Add (b);
    list.Add (ka);
}

"full interface"

    public interface InterfaceResult { }

    public abstract class Result : InterfaceResult { }
    public class ResultA : Result { }
    public class ResultB : Result { }

    public interface InterfaceKing { InterfaceResult Function (); }

    public abstract class King : InterfaceKing
    {
        public abstract InterfaceResult Function ();
    }
    public class KingA : King
    {
        public override InterfaceResult Function () => new ResultA ();
    }
    public class KingB : King
    {
        public override InterfaceResult Function () => new ResultA ();
    }

"mixed (less interface)"

    public abstract class Result { }
    public class ResultA : Result { }
    public class ResultB : Result { }

    public interface IKing { Result Function (); }

    public abstract class King : IKing
    {
        public abstract Result Function ();
    }

    public class KingA : King
    {
        public override Result Function () => new ResultA ();
    }

    public class KingB : King
    {
        public override Result Function () => new ResultB ();
        {
            return new ResultB ();
        }
    }

"no interface"

    public abstract class Result { }
    public class ResultA : Result { }
    public class ResultB : Result { }

    public abstract class King
    {
        public abstract Result Function ();
    }

    public class KingA : King
    {
        public override Result Function () => new ResultA ();
    }

    public class KingB : King
    {
        public override Result Function () => new ResultB ();
    }