Лучшие практики с событиями в C # - PullRequest
1 голос
/ 29 января 2011

В C # вы можете получить возвращаемое значение в вашей функции события. Однако вы получите только возвращаемое значение последнего события. Кроме того, похоже, нет способа получить возвращаемое значение предыдущего события.

Какие хорошие практики? Должен ли я всегда использовать void? Из моего ограниченного опыта, если я хочу объединить значения, я должен использовать ref?

Как я могу написать событие? Я хотел использовать Func , но ref там недопустимо, и я полагаю, что действие аналогично. (Я закончил с ниже). Есть ли способ сделать событие одной строкой вместо двух при использовании ref?

    delegate int FuncType(ref int a);
    static event FuncType evt;
    static void Main(string[] args)
    {
        evt += foo;
        var aa = 1;
        var a = evt(ref aa);
        evt += bar;
        var bb = 1;
        var b = evt(ref bb);
    }

    static int foo(ref int a)
    {
        a = a*3;
        return a;
    }

    static int bar(ref int a)
    {
        a=a +1;
        return a;
    }

Ответы [ 5 ]

8 голосов
/ 29 января 2011

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

Но перед этим, пожалуйста, рассмотрите возможность использования EventHandler<T> с EventArgs.

У вас может быть " все ", которое вам нужно вернуть в EventArgs.Проверьте этот пример кода:

public class BalanceChangedEventArgs : EventArgs
{
    public readonly double OldBalance;
    public readonly double NewBalance;

    public BalanceChangedEventArgs(double oldB, double newB)
    {
        OldBalance = oldB;
        NewBalance = newB;
    }
}

public class Account
{
    private double balance;

    public EventHandler<BalanceChangedEventArgs> balanceChanged;

    protected void OnBalanceChanged(BalanceChangedEventArgs eArgs)
    {
        if (balanceChanged != null)
            balanceChanged(this, eArgs);
    }

    public double Balance
    {
        get { return balance; }
        set
        {
            if (balance == value)
                return;

            OnBalanceChanged(new BalanceChangedEventArgs(balance, value));

            balance = value;
        }
    }
} 
7 голосов
/ 29 января 2011

Не путайте «событие» с «обратным вызовом». Если вы хотите предоставить «крючок» для настройки, подумайте об одном из следующих:

  • Базовый класс с виртуальными методами для ловушек.
  • Интерфейс для объекта обратного вызова, переданного в ваш конструктор или доступного через свойство.
  • Делегат передан вашему конструктору или доступен через свойство.

Если вы рассмотрели вышеизложенное и по-прежнему хотите использовать событие, тогда вы можете включить «результат» как часть типа аргумента события, например, e.Result или e.Handled. У вас все еще есть проблема с несколькими обработчиками событий, возможно, перезаписывающими значения друг друга, поэтому вы должны объединить этот подход с повторением списка вызовов, как это предлагается другими ответами. Либо сопоставьте все результаты, либо используйте стратегию «раннего выхода», подобную той, которая используется для e.Handled.

3 голосов
/ 29 января 2011

Возможно, вы захотите ознакомиться с документацией Microsoft для Event Design .

2 голосов
/ 29 января 2011

«Лучшая практика» - использовать только void обработчики событий. Именно из-за проблемы только с последним значением.

Если вы хотите объединить результаты, определите потомка EventArgs с соответствующими свойствами. Используйте список или сумму значений или что-то.

2 голосов
/ 29 января 2011

Если вы хотите получить возвращаемые значения, когда у события есть несколько подписчиков, используйте Delegate.GetInvocationList.Тогда вы можете сказать

foreach(FuncType d in evt.GetInvocationList()) {
    int value = d(parameter);
    // do something with value
}

Однако в общем случае лучше избегать возвращаемых значений в обработчиках событий.

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