Возврат значения из события - есть ли для этого хорошая практика? - PullRequest
37 голосов
/ 31 июля 2009

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

Мой вопрос здесь: это правильно? нормально ли возвращать значения из событий? или есть лучший способ сделать это? (например, использование простого делегата в форме для чтения значений)

Ответы [ 9 ]

37 голосов
/ 31 июля 2009

Часто неловко возвращать значения из событий. На практике я обнаружил, что гораздо проще включить свойство записи для набора пользовательских EventArgs, которое передается событию, а затем проверяется после его запуска - аналогично свойству Cancel события WinForms FormClosing.

28 голосов
/ 31 июля 2009

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

16 голосов
/ 31 июля 2009

Самый близкий пример, который я могу вспомнить, это событие FormClosing в WinForms. Это позволяет форме отменить событие, установив для свойства eventArgs.Cancel значение true. Чтобы сделать что-то подобное, вы должны определить свой собственный класс args события с возвращаемым значением в качестве свойства этого класса. Затем передавайте объект args события всякий раз, когда вы вызываете событие. Кто бы ни вызвал событие, он может проверить объект args события на предмет возвращаемого значения. Другие, которые получают событие, могут также проверить или изменить объект args события.

Обновление: Я только что натолкнулся на событие AppDomain.AssemblyResolve , и оно, похоже, возвращает событие. Кажется, вам просто нужно объявить тип делегата, который возвращает значение, а затем определить ваше событие с этим типом делегата. Хотя я не пытался создать свое собственное мероприятие. Одним из преимуществ использования свойства в аргументе события является то, что все подписчики на событие могут видеть, что вернули предыдущие подписчики.

13 голосов
/ 16 июля 2013

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

Создайте свой собственный класс обработчика событий

public class myCustomeEventArgs:EventArgs
{
    public bool DoOverride { get; set; }
    public string Variable1 { get; private set; }
    public string Variable2{ get; private set; }

    public myCustomeEventArgs(string variable1 , string variable2 )
    {
        DoOverride = false;
        Variable1 = variable1 ;
        Variables = variable2 ;
    }
}

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

public delegate void myCustomeEventHandler(object sender, myCustomeEventArgs e);

А в классе, вызывающем событие, вы объявляете событие.

public event myCustomeEventHandler myCustomeEvent;

Поэтому, когда вы запускаете событие в своем классе, класс, который прослушивает событие, вы можете просто в теле события установить e.DoOverride = true; как это будет объявлено в классе, запускающем событие.

Событие пожара, например:

if(myCustomeEvent != null)
{
    var eventArgs = new myCustomeEventArgs("Some Variable", "Another Varaible");
    myCustomeEvent(this, eventArgs);
    //Here you can now with the return of the event work with the event args
    if(eventArgs.DoOverride)
    {
       //Do Something
    }
}
10 голосов
/ 19 октября 2014

Примечание: только последнее событие возвращает результат.

class Program
{
static event Func<string, bool> TheEvent;

    static void Main(string[] args)
    {
        TheEvent += new Func<string, bool>(Program_TheEvent);
        TheEvent +=new Func<string,bool>(Program_TheEvent2);
        TheEvent += new Func<string, bool>(Program_TheEvent3);
        var r = TheEvent("s"); //r == flase (Program_TheEvent3)
    }

    static bool Program_TheEvent(string arg)
    {
        return true;
    }

    static bool Program_TheEvent2(string arg)
    {
        return true;
    }

    static bool Program_TheEvent3(string arg)
    {
        return false;
    }        
}
8 голосов
/ 12 июля 2011

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

   Func<DataRow, bool> IsDataValid;

   // some other code ....

   isValid = true;
   if (IsDataValid != null)
   {
      foreach (Func<DataRow, bool> func in IsDataValid.GetInvocationList())
      {
         isValid &= func(Row);
      } 
   }
1 голос
/ 19 сентября 2014

Если событие возвращает значение и зарегистрировано несколько обработчиков, событие возвращает значение результата последнего вызванного обработчика. Посмотрите на пример на http://blogs.msdn.com/b/deviations/archive/2008/11/27/event-handlers-returning-values.aspx

0 голосов
/ 28 апреля 2016

Я зациклил свойства EventArgs вот так и вытащил их значения X и Y.

private void navBarControl1_Click (отправитель объекта, EventArgs e) { int _x = 0; int _y = 0;

        Type t = e.GetType();
        IList<PropertyInfo> props = new List<PropertyInfo>(t.GetProperties());

        foreach (PropertyInfo prop in props)
        {
            if (prop.Name == "X")
            {
                object propValue = prop.GetValue(e, null);
                _x = Convert.ToInt32(propValue);
            }
            if (prop.Name == "Y")
            {
                object propValue = prop.GetValue(e, null);
                _y = Convert.ToInt32(propValue);
            }
        }
0 голосов
/ 13 декабря 2011
void method()
{
    list<string> strings = new list<string>();

    dostuff += stuff;
    dostuff += stuff;

    dostuff(this, new EventHandlerArgs(){ Parameter = strings })

    foreach(string currString in strings)
    {
          //....
    }
}

void stuff(object sender, EventHandlerArgs e)
{
    list<string> strings = e.Parameter as list<string>;

    if (strings != null)
    {
        strings.Add(MyString)
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...