重写继承方法时避免使用显式类型转换

Rob*_*nik 11 c# generics inheritance interface-implementation

我有一个基本抽象类,也实现了一个特定的接口.

public interface IMovable<TEntity, T>
    where TEntity: class
    where T: struct
{
    TEntity Move(IMover<T> moverProvider);
}

public abstract class Animal : IMovable<Animal, int>
{
    ...

    public virtual Animal Move(IMover<int> moverProvider)
    {
        // performs movement using provided mover
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我继承了一些类,其中一些必须覆盖基类的接口实现方法.

public class Snake : Animal
{
    ...

    public override Animal Move(IMover<int> moverProvider)
    {
        // perform different movement
    }
}
Run Code Online (Sandbox Code Playgroud)

我的接口方法在移动后返回相同的对象实例,因此我可以使用链接或直接在return语句中执行某些操作而不使用其他变量.

// I don't want this if methods would be void typed
var s = GetMySnake();
s.Move(provider);
return s;

// I don't want this either if at all possible
return (Snake)GetMySnake().Move(provider);

// I simply want this
return GetMySnake().Move(provider);
Run Code Online (Sandbox Code Playgroud)

正如您在我的示例中所看到的,我在子类中的覆盖返回基类类型而不是运行类.这可能需要我投出结果,我想避免.

如何定义我的接口和实现,以便我的覆盖将返回执行实例的实际类型?

public Snake Move(IMover<int> moverProvider) {}
Run Code Online (Sandbox Code Playgroud)

Lee*_*Lee 3

我建议将接口方法的返回类型更改为void并将链接行为移动到扩展方法,您可以在其中获取目标的真实类型,例如

public interface IMovable<TEntity, T>
    where TEntity : class
    where T : struct
{
    void MoveTo(IMover<T> moverProvider);
}

public abstract class Animal : IMovable<Animal, int>
{
    public virtual void MoveTo(IMover<int> mover) { }
}

public static class AnimalExtensions
{
    public static TAnimal Move<TAnimal>(this TAnimal animal, IMover<int> mover) where TAnimal : Animal, IMovable<TAnimal, int>
    {
        animal.MoveTo(mover);
        return animal;
    }
}
Run Code Online (Sandbox Code Playgroud)

Move请注意,如果您需要更广泛地应用扩展,则可以使扩展更通用:

public static TEntity Move<TEntity, T>(this TEntity entity, IMover<T> mover) where TEntity : IMovable<TEntity, T> where T : struct
{
    entity.MoveTo(mover);
    return entity;
}
Run Code Online (Sandbox Code Playgroud)