【问题标题】:this.MyEvent += new MyDel(WelcomeUser); ( What exactly meaning of this line ) [closed]this.MyEvent += new MyDel(WelcomeUser); (这条线的确切含义)[关闭]
【发布时间】:2021-11-11 11:12:36
【问题描述】:
using System;

namespace SampleApp {
   public delegate string MyDel(string str);
    
   class EventProgram {
      event MyDel MyEvent;
        
      public EventProgram() {
         this.MyEvent += new MyDel(this.WelcomeUser);
      }
      public string WelcomeUser(string username) {
         return "Welcome " + username;
      }
      static void Main(string[] args) {
         EventProgram obj1 = new EventProgram();
         string result = obj1.MyEvent("Tutorials Point");
         Console.WriteLine(result);
      }
   }
}

【问题讨论】:

  • 几个快速说明:1-您的代码不包含this.MyEvent += new MyDel...,但包含this.MyEvent = new MyDel...。这看起来像你的问题中的错字。 2- 该行是您订阅该事件的位置。因为不同的代理可以订阅同一个事件,这就是为什么订阅通常是附加的(使用event += delegate 语法)。在您当前的代码中,由于该事件不是公开的,因此应该可以使用event = delegate(您的班级是唯一能够订阅它的班级)
  • 你从哪里得到这个样本的?对于理解为什么以及何时需要事件,它比帮助更令人困惑。
  • @Steve 我想知道该代码是否可以编译,可能需要public event 以便其他人可以订阅它。我认为c# reference event documentation 更清楚
  • 你可能需要知道什么是委托以及如何使用check this question 或者需要知道什么是事件以及如何使用this question is usefull
  • @Mr.Wadile += 在订阅事件时的作用是因为通常事件的意图使用是“允许每个人都订阅它”并且因为使用+= 运算符(允许多个订阅)。如果您只使用event = function1;,然后再使用event = function2;,因为= 的用法,第一个函数将永远不会被调用......并且调试错误的行为会让人头疼。

标签: c# events delegates


【解决方案1】:

使用 events 的想法是为某些对象提供能力,该对象存储此事件(称为“发布者”)通知订阅此事件的其他一些对象(称为“订阅者”),发生了什么事。

您的示例可能会以“当某些用户加入时通知”的方式使用。它使用某种"Publisher-Subscriber pattern"

所以,您有一些EventProgram 类,它是存储事件OnUserJoin 的“发布者”,每次用户加入时都会触发该事件(添加到List)。添加新用户后通过调用OnUserJoinEventHandler 提供事件触发。在调用它时,我们提供usernameUserJoinedEventArgs - 这是“发生了什么”的一种“细节”。 OnUserJoin?(和?)表示检查,有一些“订阅者”我们可以向谁“发送通知”。

public class EventProgram
{
    private readonly List<string> users;

    // Publishing event for "subscribers"
    public event EventHandler<UserJoinedEventArgs> OnUserJoin;

    public EventProgram() 
    {
        users = new List<string>();
    }

    public void AddNewUser(string username)
    {
        // Adding new user
        users.Add(username);
        // And calling event to notify "subscribers" that we added provided user
        OnUserJoin?.Invoke(this, new UserJoinedEventArgs { Username = username });
    }
}

// Custom details for our event
public class UserJoinedEventArgs
{
    public string Username { get; set; }
    // and other details you wish to provide about joined user
}

将它用作“订阅者”是创建处理程序(例如HandleUserJoin),它将“接受来自“发布者”类的通知,并使用来自UserJoinedEventArgs 的接受的详细信息做一些事情。

void Main(string[] args = default)
{ 
    EventProgram eventProgram = new EventProgram();
    // "Subscribing" to "publisher"'s event with `HandleUserJoin` handler
    eventProgram.OnUserJoin += HandleUserJoin;

    // Adding new user
    eventProgram.AddNewUser("Mr.Wadile");
}

// This handler is actually "subscriber", which waits for notifications
// from "publisher"'s OnUserJoin event with details, provided
// as UserJoinedEventArgs
private void HandleUserJoin(object sender, UserJoinedEventArgs args)
{
    Console.WriteLine("Welcome, " + args.Username);
} 

结果,每次我们使用.AddNewUser("Some Username") 添加新用户时-“发布者”EventProgram 将通过OnUserJoin 事件通知我们,当我们在HandleUserJoin 中“接受”此通知时-我们打印欢迎消息。

回答有关+= 运算符的问题 - 这实际上是“订阅”过程,当您“订阅”HandleUserJoin 方法以接收来自OnUserJoin 事件的通知时(在本例中)。

委托通常是指向某些方法的“指针”,这些方法与委托签名相匹配。根据上面的示例,您可以使用委托来组合不同的操作并将它们全部称为一个:

public class EventProgram
{
    private readonly List<string> users;
    // Delegate declaration with "void (string)" signature
    public delegate void JoinUser(string username);

    // A field of delegate type, that will be used to call from other classes
    public JoinUser JoinNewUser;

    public EventProgram()
    {
        users = new List<string>();

        // Combining different actions with User into one delegate
        // First - assigning with "=" (+= can be used too)
        JoinNewUser = AddUserToDatabase;
        // Next - appending with "+="
        JoinNewUser += WelcomeUser;
        JoinNewUser += SendWelcomeGiftToUser;
    }

    // Matches to delegate signature "void (string)"
    private void AddUserToDatabase(string username)
    {
        users.Add(username);
        Console.WriteLine("New user \"" + username + "\" added to database!");
    }
   
    // Matches to delegate signature "void (string)"
    private void WelcomeUser(string username) =>
        Console.WriteLine("Welcome, " + username);

    // Matches to delegate signature "void (string)"
    private void SendWelcomeGiftToUser(string username) =>
        Console.WriteLine(username + ", we sending you 100$ as a welcome gift!");
}

所以在创建EventProgram 的实例后,我们只需在其他类中调用JoinNewUser,所有3 个动作都将被委托调用:

void Main(string[] args = default)
{
    EventProgram eventProgram = new EventProgram();
    eventProgram.JoinNewUser("Mr.Wadile");
}

所以它看起来像:

+= 运算符通常在订阅事件时使用,因为= 运算符将替换“委托堆栈”并且只执行最后一个委托。例如,在前面的例子中:

JoinNewUser = AddUserToDatabase;
JoinNewUser = WelcomeUser;
JoinNewUser = SendWelcomeGiftToUser;

只会输出SendWelcomeGiftToUser 委托,而不是预期的三个委托/函数/方法:

Wadile 先生,我们送您 100 美元作为欢迎礼物

【讨论】:

  • 关于+= 的用法,我要补充一点,= 可以使用,但通常+= 用于允许对同一事件的多个订阅,否则只有最后一个委托是触发事件时调用。还是不错的答案
  • @Cleptus,我试图在描述代表部分答案时显示= / += 用法。也许不是你的意思,所以请随时纠正我。
  • 编辑了你的答案,检查编辑,如果你觉得它是错误的或偏离你的意图,请随时回滚编辑/删除/更正它。
  • @Cleptus,谢谢,现在看起来更清晰的解释了。
  • 感谢您帮助理解
猜你喜欢
  • 1970-01-01
  • 2013-08-20
  • 2015-05-16
  • 1970-01-01
  • 2014-02-17
  • 1970-01-01
  • 2019-05-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多