2015-06-02 2 views
1

Я пытаюсь правильно понять Events и EventArgs, но не могу получить ручку в целом EventArgs.Empty.Выполнение EventArgs Пустой Правильно

EventArgs инвентарь:

public static readonly EventArgs Empty; 

и позволяет создать EventHandler и вызвать его с помощью:

public event EventHandler<EventArgs> TestHappening; 

private void MyMethod() 
{ 
    TestHappening(this, EventArgs.Empty); 
} 

Теперь я изучил ряд классов, основанных на EventArgs и ни один из них не кажется, чтобы реализовать это, поэтому я лечу немного вслепую, хотя я прочитал всю документацию, которую я смог найти относительно EventArgs.Empty. Согласно документации, «Значение Empty является экземпляром EventArg, доступным только для чтения, эквивалентным результату вызова конструктора EventArgs».

Основываясь на том, что я создал следующую реализацию:

public class TestEventArgs : EventArgs 
{ 
    public static readonly TestEventArgs Empty; 

    public bool UpdatedValue { get; private set; } 

    TestEventArgs() 
     : this(false) 
    { 
    } 

    public TestEventArgs(bool updatedValue) 
    { 
     this.UpdatedValue = updatedValue; 
    } 
} 

public event EventHandler<TestEventArgs> TestHappening; 

private void MyMethod() 
{ 
    TestHappening(this, EventArgs.Empty); 
} 

является использование TestEventArgs.Empty Instancing класс или что именно он делает?

Кроме того, несмотря на то, что все подклассы, которые я проверил, не использовали Empty, они все еще имеют его доступными, разве это не запутывает наличие непригодного для использования свойства?

Наконец, на основе различных документов, которые я изучал, было два основных отклонения от того, когда фактически создавать экземпляр EventArgs. Что считается «более» правильный ?:

OnTestHappening(new TestEventArgs(false)); 

private void OnTestHappening(TestEventArgs e) 
{ 
    var handler = TestHappening; 

    if (handler != null) 
     handler(this, e); 
} 

против

OnTestHappening(true); 

private void OnTestHappening(bool foo) 
{ 
    var handler = TestHappening; 

    if (handler != null) 
     handler(this, new TestEventArgs(foo)); 
} 
+1

Класс EventArgs предназначен для базового класса. Для более специализированных классов событий, которые действительно имеют полезные свойства. Вы не знаете, когда вы когда-нибудь захотите этого класса. Итак, вы начинаете с EventArgs и можете очень легко изменить его, не нарушая никаких обработчиков событий. Пока не наступит этот день, вам нужно передать экземпляр EventArgs. Вы можете использовать 'new EventArgs()', но это бесполезно, EventArgs.Empty - дешевая альтернатива. –

+1

Даже не имеет смысла иметь «пустой» экземпляр этого класса в первую очередь. Когда вы создаете этот класс, вы должны ожидать, что люди будут фактически создавать логическое значение при создании экземпляра, а не использовать значение по умолчанию. – Servy

+0

@Servy: Я согласен, я просто пытаюсь полностью понять, как это работает и понял, если я сломал его, как я, это может помочь какой-то другой потерянной душе однажды :) – Storm

ответ

2

Вы должны думать, для себя, если вам действительно нужно Empty поле. Если вы не используете его, вы не должны его создавать. Класс EventArgs не имеет никаких переменных или свойств, поэтому нет смысла создавать новый экземпляр каждый раз. В вашем случае, поскольку у вас есть значение по умолчанию, имеет смысл иметь два «пустых» TestEventArgs, один для true и один для false (если вы действительно этого хотите, и это имеет смысл в вашем сценарии).

Вы отсутствуют некоторые другие моменты в вашей реализации, которые я закрепилась ниже:

public class TestEventArgs : EventArgs 
{ 
    public static new readonly TestEventArgs True = new TestEventArgs(true); 

    public static new readonly TestEventArgs False = new TestEventArgs(false); 

    public bool UpdatedValue { get; private set; } 

    public TestEventArgs(bool updatedValue) 
    { 
     this.UpdatedValue = updatedValue; 
    } 

    public event EventHandler<TestEventArgs> TestHappening; 

    private void MyMethod() 
    { 
     EventHandler<TestEventArgs> eh = TestHappening; 

     if (eh != null) 
     { 
      eh(this, TestEventArgs.Empty); 
     } 
    } 
} 

Что изменилось:

  1. конкретизированных Empty как new TestEventArgs, так как это было определение EventArgs.Empty слишком.
  2. Я реализовал потокобезопасную версию обработчика событий (второй образец в вашем коде). Если список обработчиков событий, подписанных на событие, изменяется, ваш первый образец небезопасен. Ваша вторая, и, следовательно, вы должны это сделать.

Что касается вашего последнего пункта: это зависит от того, хотите ли вы, чтобы вызывающие делегаты меняли объект (он передает один экземпляр против нескольких экземпляров). В вашем случае, поскольку экземпляр не может быть изменен, это не имеет большого значения.

+0

Хорошо, теперь это имеет большой смысл, я просто не мог сделать головы или хвосты, я, должно быть, уже думал об этом. Что касается безопасности потоков, спасибо за указание на это, я все еще пытаюсь на самом деле получить это под коленом, почему «TestHappening (this, EventArgs.Empty)» не является потокобезопасным и у вас есть ссылка на что-то, что объясняет это еще? Я читал многочисленные рецензии по безопасности потоков, но просто не могу понять, как это прибилось. – Storm

+1

@Storm: [This] (http://stackoverflow.com/q/2582052/993547) подводит итог очень хорошо. –

+0

Awesome Patrick, не могли бы вы просто ответить на мой третий вопрос выше в своем ответе, пожалуйста? – Storm