2017-10-02 7 views
3

Pourquoi le code suivant n'imprime pas "Hello, World!"?Pourquoi les événements C# ne peuvent pas être directement souscrits à d'autres événements

using System; 

namespace Test 
{ 
    public class Program 
    { 
     public static void Main(string[] args) 
     { 
      var a = new A(); 
      var b = new B(a); 
      b.Evnt += val => Console.WriteLine(val); 
      a.Do(); 
     } 
    } 

    public class A 
    { 
     public void Do() 
     { 
      Evnt("Hello, World!"); 
     } 

     public event Action<string> Evnt = v => {}; 
    } 

    public class B 
    { 

     public B(A a) 
     { 
      a.Evnt += Evnt; // this does not work 
     } 

     public event Action<string> Evnt = v => {}; 

    } 
} 

Mais si je remplace la ligne

a.Evnt += Evnt; 

avec

a.Evnt += v => Evnt(v); 

tout fonctionne très bien.

Si cela est interdit, quel sens a souscrit un événement à un autre, et pourquoi n'y a-t-il pas d'erreur de compilation ou d'avertissement?

Répondre

5

Il échoue pour la même raison cette impression de code « 2 »:

int x = 2; 
int y = x; 

Action a =() => Console.WriteLine(y); 

x = 3; 
a(); 

Ici, votre gestionnaire d'événements est la valeur de a.Evntau moment de la cession - quel que soit a a pour Evnt au Lorsque vous passez le a dans le constructeur B, c'est ce que B obtient pour un gestionnaire d'événements.

public B(A a) 
{ 
    a.Evnt += Evnt; // this does not work 
} 

Il fonctionne réellement bien - il fait ce que vous avez dit à. C'est juste que tu pensais que tu lui disais de faire quelque chose de différent.

Ici, vous avez un gestionnaire qui évalue lui-même Evnt, peu importe le moment où le gestionnaire est exécuté. Donc, avec celui-ci, si a.Evnt est modifié entre-temps, vous verrez la sortie de la nouvelle valeur de a.Evnt.

public B(A a) 
{ 
    a.Evnt += v => Evnt(v); 
} 

Rewrite B comme ça, et vous obtiendrez une image plus claire:

public class B 
{ 

    public B(A a) 
    { 
     a.Evnt += Evnt; // this does not work 
    } 

    public event Action<string> Evnt = v => { Console.WriteLine("Original"); }; 

} 

Le titre de votre question est mal formulée; vous n'attribuez pas d'événement, vous affectez un gestionnaire d'événement. En outre, "cela ne fonctionne pas" n'est pas un moyen utile de décrire un problème. Il y a une infinité de façons pour que les choses ne fonctionnent pas. Ma première hypothèse était que votre code ne serait même pas compilé. La prochaine fois, veuillez décrire le comportement que vous attendiez et ce que vous avez vu à la place. Dites s'il a échoué à compiler, ou si vous avez lancé une exception lors de l'exécution, ou si vous avez simplement fait quelque chose que vous n'aviez pas anticipé. S'il y a un message d'erreur ou un message d'exception, fournissez le texte du message.

0

Comme lambda évalue et capture sur appel, sinon + = attache une fois, puis appelé ref (sans évaluation)