Подтвердить что ты не робот

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

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

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

4b9b3361

Ответ 1

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

Ответ 2

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

Ответ 3

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

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

Ответ 4

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

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

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; как он будет объявлен в классе, запускающем событие.

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

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
    }
}

Ответ 5

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

   Func<DataRow, bool> IsDataValid;

   // some other code ....

   isValid = true;
   if (IsDataValid != null)
   {
      foreach (Func<DataRow, bool> func in IsDataValid.GetInvocationList())
      {
         isValid &= func(Row);
      } 
   }

Ответ 6

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

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

Я зацикливал свойства 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);
            }
        }

Ответ 9

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)
    }
}