【问题标题】:[C#][Events] Is this correct? New to c#[C#][事件] 这是正确的吗? c#新手
【发布时间】:2020-06-23 00:58:54
【问题描述】:

一直在尝试学习 c# 并尝试事件。已经尝试过了,并得到了一些功能。查看我的代码时,它看起来很奇怪,因为我必须为每个订阅者创建新对象,然后订阅发布者。我是否需要创建新对象,然后使用该对象订阅发布者?

程序.cs

namespace ConsoleApp1
{
    class Program
    {
        public static void Main()
        {
            ExternalClass potato = new ExternalClass();
            potato.Start();
            
        }
    }
}

外部类.cs

using System;

namespace ConsoleApp1
{
    class ExternalClass
    {
    
        //This is the event, which is the actual event you call to trigger all of the other method/function calls.
    
        public void Start()
        {
            string SubscribeMessage = "Subscribing...";
            string UnsubscribeMessage = "Unsubscribing";
            Apple potato = new Apple();
            Orange beet = new Orange();
            //adding a function to an event
            Console.WriteLine(SubscribeMessage);
            potato.MyEvent += potato.helloWorld;
            potato.MyEvent += beet.DisplayOrange;
            potato.OnEventSuccess();
            //unsubscribing from an event
            Console.WriteLine(UnsubscribeMessage);
            potato.MyEvent -= beet.DisplayOrange;
            potato.MyEvent -= potato.helloWorld;
            potato.OnEventSuccess();
        
        }
    }
}

Apple.cs

using System;

namespace ConsoleApp1
{
    class Apple
    {
        public event Action MyEvent;
    
        //This is the function that you wish to call when you call the event. All other function/method calls must have the same shape as the delegate
        public void helloWorld()
        {
            Console.WriteLine("Hello world!");
        }

        public void OnEventSuccess()
        {
            //myEvent?.Invoke();
            if (MyEvent != null)
            {
                MyEvent?.Invoke();
            }
            else
            {
                Console.WriteLine("Event is empty!");
            }
        }
    }
}

Orange.cs

using System;

namespace ConsoleApp1
{
    public class Orange
    {
        public void DisplayOrange()
        {
            Console.WriteLine("Orange is functioning");
        }
    }
}

样本输出:

Subscribing...
Hello world!
Orange is functioning
Unsubscribing
Event is empty!

【问题讨论】:

  • 你觉得创建发布者很奇怪还是创建订阅者很奇怪?
  • @LouisGo 可能在 start 方法中创建订阅者感觉很奇怪?
  • 您不必为每个事件都实例化一个全新的对象,您可以向该事件注册任何您想要的方法,只要签名匹配即可。
  • @entropic 你是说从一个对象到一个事件的多种方法吗?还是一个对象订阅多个事件?我很确定第一个是可能的,第二个我知道是可能的。
  • 我是说如果你愿意,你根本不需要Orange 类,你可以在ExternalClass 中编写DisplayOrange() 函数并将其注册到事件中

标签: c# events


【解决方案1】:

到目前为止,您的代码还可以。

对于您的问题:

您似乎觉得创建新订阅者不太好。 我会说目前还可以,除非您提供有关代码的更多上下文。

事件是一种让两个对象在解耦的同时进行通信的方式,因此订阅者或发布者的生命周期并不重要。 只需确保它们在触发事件时同时存在,并在未使用时取消订阅。

但是,您的代码“可能”存在潜在的内存泄漏。 假设这个potato是一个成员变量,它的寿命比beet长。

一旦退订前发生任何异常,将永远不会退订,beet 将与potato 一样长。

    Apple potato = new Apple();
    public void Start()
    {
        string SubscribeMessage = "Subscribing...";
        string UnsubscribeMessage = "Unsubscribing";
        Orange beet = new Orange();
        //adding a function to an event
        Console.WriteLine(SubscribeMessage);
        potato.MyEvent += potato.helloWorld;
        potato.MyEvent += beet.DisplayOrange;
        potato.OnEventSuccess();

        // .... another operation
        // Something bad happened on the operation.
        // An exception is thrown then it never goes to Unsubscribe part.
        //unsubscribing from an event
        Console.WriteLine(UnsubscribeMessage);
        potato.MyEvent -= beet.DisplayOrange;
        potato.MyEvent -= potato.helloWorld;
        potato.OnEventSuccess();
    
    }

参考:How to avoid event handler memory leaks

【讨论】:

    猜你喜欢
    • 2011-04-25
    • 1970-01-01
    • 1970-01-01
    • 2012-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多