Назначение событий в инициализаторе объекта - PullRequest
21 голосов
/ 22 октября 2010

Почему невозможно назначить события вместе со свойствами в инициализаторах объектов в C #? Это кажется естественным.

var myObject = new MyClass()
     {
        Property = value,
        Event1 = actor,
        // or
        Event2 += actor
     };  

Или есть какой-то трюк, о котором я не знаю?

Ответы [ 3 ]

6 голосов
/ 22 октября 2010

Что касается внешнего контракта, событие не имеет установщика, только методы add и remove - подписчики могут регистрироваться и отменять регистрацию на событии, а объект публикации решает, когда вызывать обратные вызовы, «вызывая» событие.Следовательно, идея «назначить событие», вообще, бессмысленна.

Однако, когда вы объявляете событие в классе, компилятор C # предоставляет вам действительно удобную функцию: когда вы не предоставляете свою собственную реализацию, он создает private , резервное поле делегата для вас, вместе с соответствующими реализациями добавления / удаления.Это позволяет вам «установить событие» (действительно поле поддержки) внутри класса, но не за его пределами.Чтобы понять это, рассмотрим:

public class Foo
{
    // implemented by compiler
    public event EventHandler MyEvent;

    public static Foo FooFactory(EventHandler myEventDefault)
    {
       // setting the "event" : perfectly legal
       return new Foo { MyEvent = myEventDefault }; 
    }
}

public class Bar
{
    public static Foo FooFactory(EventHandler myEventDefault)
    {
        // meaningless: won't compile
        return new Foo { MyEvent = myEventDefault };
    }
}


public class Baz
{
    // custom implementation
    public event EventHandler MyEvent
    {      
        add { }  // you can imagine some complex implementation here
        remove { } // and here
    }

    public static Baz BazFactory(EventHandler myEventDefault)
    {
        // also meaningless: won't compile
        return new Baz { MyEvent = myEventDefault };
    }
}
4 голосов
/ 22 октября 2010

Вы можете использовать операторы += или -+ только для события вне класса его владельца.

public class Data
{
   public event EventHandler OnSave = (s,e) => 
      {
         //do something important!
      };

   public void Save()
   {
      OnSave(this,null);
      //do save
   }
}
//outside the class
Data data = new Data { OnSave = null }; //compile error
data.OnSave = SomeMethodElse;  //compile error
data.OnSave += MyCustomActionsOnSave;  //ok
data.Save();

Вы не можете удалить действие OnSave, определенное в классе. Вы можете только добавлять / удалять свои собственные действия OnSave вне класса. Если вы удалите ключевое слово event, OnSave будет уже не событием, а обычным делегатом. Затем вы можете делать что угодно, включая присваивание значения за пределами класса.

3 голосов
/ 07 января 2018

Это не относится к C # 6 или C # 7 (с момента первоначального вопроса), однако не было решено против. На GitHub существует проблема, которая отслеживает языковое предложение. Вы можете проголосовать за него там, а также перейти по ссылкам к предыдущему обсуждению этой функции.

https://github.com/dotnet/csharplang/issues/307

Если вы хотите увидеть эту функцию, добавьте вопрос к проблеме, чтобы повысить ее наглядность.

Предлагаемый синтаксис:

var timer = new DispatcherTimer {
    Tick += delegate {},
    Interval = TimeSpan.FromSeconds(1d),
};
...