Считается ли использование Action.Invoke лучшей практикой? - PullRequest
29 голосов
/ 13 февраля 2012

Если у меня есть приведенный ниже код, я должен просто вызвать Action или вызвать Action.Invoke?

public class ClassA
{
  public event Action<string> OnAdd;

  private void SomethingHappened()
  {
    if (OnAdd != null)
     OnAdd("It Happened"); //Should it be OnAdd.Invoke("It Happened") ???????
  }
}

public class ClassB
{

  public ClassB()
  {
    var myClass = new ClassA();
    myClass.OnAdd += Add;
  }

  private void Add(string Input)
  {
    //do something
  }  
}

Ответы [ 4 ]

37 голосов
/ 13 февраля 2012

Эти два значения эквивалентны, компилятор преобразует OnAdd("It Happened"); в OnAdd.Invoke("It Happened"); для вас.

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

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

private void SomethingHappened()
{
  Action<string> local = OnAdd;
  if (local != null)
  {
    local("It Happened");
  }
}
11 голосов
/ 13 февраля 2012

Две конструкции совершенно эквивалентны.

OnAdd("It Happened");

это просто синтаксический сахар. За кулисами компилятор отправляет вызов Action<T>.Invoke в полученном MSIL. Так что используйте тот, который более читабелен для вас (для меня OnAdd("It Happened"); достаточно для чтения).

10 голосов
/ 07 января 2016

Что-то, что я заметил по этому поводу в последней версии C # 6, так как это может побудить Invoke использовать больше, и подумал, что я добавлю это к этому старому вопросу на случай, если это кому-нибудь поможет:

«Старый» путь:

Action<string> doSomething = null; // or not null
if (doSomething != null)
    doSomething("test");

Возможный прагматичный способ (аналог пустого шаблона делегата события):

Action<string> doSomethingPragmatic = s => { }; // empty - might be overwritten later
doSomethingPragmatic("test");

C # 6:

Action<string> doSomethingCs6 = null; // or not null
doSomethingCs6?.Invoke("test");

// Not valid C#:
// doSomethingCs6?("test")
// doSomethingCs6?.("test")
6 голосов
/ 13 февраля 2012

Они в точности эквивалентны, если только вы не столкнетесь с очень странной ошибкой вокруг анонимных функций .

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

if (callAsync)
{
    var result = foo.BeginInvoke(...);
    // ...
}
else
{
    foo.Invoke(...);
    // ...
}

Здесь явное использование Invoke полезно для симметрии.

См. Раздел 15.4 спецификации C # 4 для более подробной информации о вызове делегата, хотя он явно не определяет его с точки зрения вызова метода Invoke.

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