Перегрузка абстрактных обобщенных методов в C#

Я пытаюсь реализовать общий абстрактный метод с ограничением типов, а затем реализовать его несколько раз, используя различные указанные типы.

public abstract class Ability
{
   public abstract void BindToStation<T>(T station) where T : Station;
}

public class DashAbility : Ability
{
    public override void BindToStation<NavStation>(NavStation station){ }
    public override void BindToStation<CannonStation>(CannonStation station){ }
}

Но я получаю ошибку, которая говорит, что метод уже был определен с теми же типами параметров.

Я предполагаю, что компилятор рассматривает любой универсальный параметр как один и тот же с точки зрения сигнатуры метода, поэтому эти два метода выглядят одинаково.

Тем не менее, мне интересно, если есть способ перегрузить общий метод с использованием определенных типов..?

2 ответа

Вы не можете делать именно то, что вы хотите, но вы можете попробовать такой подход:

interface IBindableTo<T> where T : Station
{
    void BindToStation(T station);
}

abstract class Ability
{
    public abstract void BindToStation<T>(T station) where T : Station;
}

class DashAbility : Ability, IBindableTo<NavStation>, IBindableTo<CannonStation>
{
    public override void BindToStation<T>(T station)
    {
        if (this is IBindableTo<T> binnder)
        {
            binnder.BindToStation(station);
            return;
        }

        throw new NotSupportedException();
    }

    void IBindableTo<NavStation>.BindToStation(NavStation station)
    {
        ...
    }

    void IBindableTo<CannonStation>.BindToStation(CannonStation station)
    {
        ...
    }
}

Надеюсь это поможет.

C# не поддерживает специализацию таким образом, как и C++, когда вы хотите специализироваться на типе времени выполнения.

Но вы можете использовать полиморфизм, поэтому вы можете использовать двойную диспетчеризацию:

public abstract class Station {
    internal abstract void DashBindToStation();
}

public class NavStation : Station {
    internal override void DashBindToStation() {
        throw new NotImplementedException();
    }
}

public class CannonStation : Station {
    internal override void DashBindToStation() {
        throw new NotImplementedException();
    }
}

public abstract class Ability {
    public abstract void BindToStation(Station station);
}

public class DashAbility : Ability {
    public override void BindToStation(Station station) {
        station.DashBindToStation();
    }
}

Другая возможность в C# - использовать диспетчеризацию во время выполнения, используя dynamic:

public abstract class Station {
}

public class NavStation : Station {
}

public class CannonStation : Station {
}

public abstract class Ability {
    public abstract void BindToStation(Station station);
}

public class DashAbility : Ability {
    public void BindToStation(NavStation station) {
    }
    public void BindToStation(CannonStation station) {
    }

    public override void BindToStation(Station station) {
        BindToStation((dynamic)station);
    }
}
Другие вопросы по тегам