Использовать перегрузку с производными классами для потока управления - PullRequest
3 голосов
/ 15 апреля 2020

Я новичок в C#, и я хотел узнать, есть ли способ использовать перегрузку методов для управления потоком программ.

Итак, моя проблема в том, что у меня есть метод, сигнатура которого я не могу например:

public void Event(Args args) { }

Теперь класс Args содержит ссылку на абстрактный класс с именем Base. Base может быть производными классами A или B во время выполнения.

Теперь я хочу сделать разные вещи в зависимости от того, какой производный класс передан. Чтобы быть расширяемым, я знаю, что позже будет больше производных классов, таких как C и D, возможно, также Base больше не является абстрактным.

То, что я сейчас делаю для управления потоком программы, следующее:

public void Event(Args args) {
    if(args.handle is A a) 
        foo(a);
    else if(args.handle is B b)
        foo(b);
}

С двумя различными методами foo(...): foo(A a) и foo(B b)

Есть ли способ избавиться от операторов if else, чтобы c# -Run-time выбирал правильный foo на основе своего самого производного класса до самого высокого неабстрактного класса (я уверен, что должен реализовать все их).

Я также не могу изменить Base и сделать foo его виртуальным методом.

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

Полный код выглядит следующим образом:

public abstract class Base{}

public class A : Base {}

public class B : Base {}

public class Args {

    public Base handle = new A();
}

public class Program
{
    public static void Main()
    {
        Event(new Args());
    }

    public static void foo(A a) {}

    public static void foo(B b) {}


    public static void Event(Args args) {
        foo(args.handle); // here the error occures 
    }
}

1 Ответ

4 голосов
/ 15 апреля 2020

Весь смысл полиморфизма состоит в том, чтобы включить привязку во время выполнения для реальных вызовов. Поэтому, если у вас есть эти методы:

Foo(A a) { ... }
Foo(B b) { ... }

и вызовите его так:

Foo((Base)args.base);

, среда выполнения выбирает наиболее приемлемую (то есть наиболее конкретную c) перегрузку. Вам не нужно самим включать фактический тип.

РЕДАКТИРОВАТЬ: Вам также нужен метод для случая, когда события Handler не являются ни A, ни B:

Foo(Base b) { ... }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...