2010-10-22 22 views
17

Perché non è possibile assegnare eventi insieme alle proprietà negli inizializzatori di oggetti in C#? Sembra essere così naturale farlo.Assegnazione di eventi nell'inizializzatore di oggetti

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

Oppure c'è qualche trucco che non conosco?

+0

Sembra che questa funzione sta per essere aggiunto nella prossima versione di lingua http://roslyn.codeplex.com/wikipage?title=Language+Feature+Status – Zarat

+0

Se sei ancora interessato, per favore guarda il mio suggerimento qui: http://stackoverflow.com/questions/24951619/add-event-handler-during-object-initialization/37994490#37994490 –

risposta

5

quanto l'appalto esterno è interessato, un evento non ha un setter, solo add e removemetodi - gli abbonati possono registrarsi e annullare la registrazione dalla manifestazione, e la pubblicazione di oggetto decide quando per richiamare le callback "sollevando" l'evento. Di conseguenza, l'idea di "assegnare un evento", in generale, non ha senso.

Tuttavia, quando si dichiara un evento in una classe, il compilatore C# fornisce ciò che è veramente vantaggio di funzionalità: quando non si fornisce la propria implementazione, si crea un privato, il backup delegato campo per te, insieme alle appropriate implementazioni di aggiunta/rimozione. Ciò consente di "impostare l'evento" (in realtà il campo di supporto) all'interno della classe, ma non al di fuori di esso. Per capire questo, si consideri:

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 }; 
    } 
} 
+5

Questo non ha nulla a che fare con la restrizione. Le proprietà hanno metodi di setter e campi di backing privati, eppure l'inizializzatore di oggetti funziona bene con quelli. –

3

È possibile utilizzare gli operatori += o -+ solo per un evento esterno alla classe del proprietario.

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(); 

Non è possibile rimuovere il OnSave azione definita nella classe. Puoi aggiungere/rimuovere le tue azioni OnSave al di fuori della classe. Se rimuovi la parola chiave event, lo OnSave non sarà più un evento, ma un ordinario delegato. Quindi puoi fare qualsiasi cosa, inclusa l'assegnazione di valore al di fuori della classe.

+0

È (volendo) usare '+ =' . –

1

Questo non ha fatto C# 6 o C# 7 (dal momento che la domanda iniziale), tuttavia non è stato deciso contro. C'è un problema su GitHub che tiene traccia della proposta linguistica. Puoi votare lì, così come seguire i link nella discussione precedente attorno alla funzione.

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

Se vuoi vedere questa funzione, aggiungere un pollice in su per la questione per contribuire ad aumentare la sua visibilità.

La sintassi proposto è:

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