【问题标题】:Can I use something else instead of "this" in this code? [closed]我可以在这段代码中使用其他东西而不是“this”吗? [关闭]
【发布时间】:2015-10-15 07:57:02
【问题描述】:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Event_training
{
    class Publisher
    {
        public event EventHandler x;

        public void raise()
        {
            x(this, null);
        }

    }

    class Subscriber
    {
        public void method1(object o, EventArgs e)
        {
            Console.WriteLine("metod1 called");
        }

        public void method2(object o, EventArgs e)
        {
            Console.WriteLine("metod2 called");
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            Publisher p = new Publisher();
            Subscriber s = new Subscriber();

            p.x += s.method1;
            p.x += s.method2;

            p.raise();
        }
    }
}

很难理解“this”关键字。它指的是什么“x(this, null);”在这里?我可以用其他东西代替“this”吗?

【问题讨论】:

  • 请阅读this (C# Reference)并关闭问题
  • this 指的是Publisher的当前实例。
  • 我为什么要把它的实例交给它的方法?
  • 我们怎么知道你为什么这样做?
  • @Lyrk x 是一个 EventHandler ,它接受一个 sender (引发事件的原因),在这种情况下是您的类实例,以及您作为 null 传递的 EventArgs。如果您特别问为什么要这样做,那么只有您可以回答这个问题。

标签: c# events this


【解决方案1】:

为什么需要传递Publisher 的实例?假设您有多个发布者和一个订阅者:

 Publisher p1 = new Publisher() { Name = "Bob" };
 Publisher p2 = new Publisher() { Name = "Joe" };
 Subscriber s = new Subscriber();

您订阅了两个发布者的x 事件:

 p1.x += s.method1;
 p2.x += s.method1;

现在的问题 - 您如何知道哪个发布者在事件句柄中引发了事件?

public void method1(object o, EventArgs e)
{
    Console.WriteLine("metod1 called");
}

这就是为什么默认的EventHandler 委托有两个参数。第一个通常称为sender 而不是o。这样您就可以检查sender 并了解哪个发布者引发了事件。假设Publisher 也有Name 属性:

class Publisher
{
    public event EventHandler x;
    public string Name { get; set; }        

    public void Raise()
    {
       EventHandler x = this.x;
       if (x != null)
          x(this, EventArgs.Empty);
    }
}

现在在事件处理程序中您可以获得发布者的名称,因为您已经将发布者实例 (this) 传递给了事件处理程序:

public void method1(object sender, EventArgs e)
{
    Publisher publisher = (Publisher)sender;
    Console.WriteLine(publisher.Name + " raised event x");
}

如果您不需要传递任何事件参数和引发事件的对象实例,那么您可以使用其他类型的委托进行事件。例如。 Actiondelegate 没有任何参数。

class Publisher
{
    public event Action x;      

    public void Raise()
    {
       Action x = this.x;
       if (x != null)
          x(); // No parameters
    }
}

处理程序看起来像:

public void method1()
{
    Console.WriteLine("metod1 called");
}

【讨论】:

  • 感谢您的详细回答。我想我现在明白了。
  • @Lyrk good :) 正如 Dmitry 所说,EventHandler 代表的使用是一种标准,它从 WinForms 开发开始。微软的一些人决定你总是需要知道事件的发送者。并通过所有WinForms 系统实现了这个EventHandler 方法。任何事件(按钮单击、隐藏/显示控件等)都是通过 EventHandler 委托实现的。但是你在这里不受限制,你可以使用任何你想要的委托类型。但我的建议 - 不要混合使用不同的方法。
  • 有时微软开发人员创建的这些快捷方式会让人们很难理解不了解过去实现的人。
【解决方案2】:

this 指类的当前时刻。

例如:

Publisher publisher = new Publisher();
publisher.raise();

在这种情况下,thispublisher 实例。如果我像这样向您展示它,也许会更清楚: publisher.x(publisher, null);

此外,在您的情况下,甚至没有使用第一个参数。所以你也可以写null, null

您所称的object o 通常称为sender。这是有道理的,因为引发事件的任何对象都会通过此参数传递。

如果您想了解有关 this 关键字的更多信息,请参阅 microsoft 网站 (link)

【讨论】:

  • 例如在上面的代码中,我在 main.js 中创建了一个名为“p”的 Publisher 类的实例。 “this”指的是“p”。这是真的吗?
  • this 只是当前实例。如果方法中有 this 关键字。然后 this 关键字在您的情况下指的是 p 。如果您有多个 Publisher 实例,它们都引用了正确的实例。喜欢:Publisher p = new Publisher(); Publisher pub = new Publisher();。其中raise 中的this 关键字等于调用该方法的实例。喜欢:thispub 当做 pub.raise()thispp.raise()
  • 感谢您的回答。
【解决方案3】:

标准模式是

// it's not a public method 
internal void raise()
{
    // local copy for being thread safe
    var localX = x;

    // do not forget to check for null
    if (null != localX)
      localX(this, EventArgs.Empty); // standard EventArgs.Empty, not null
}

注意,this标准模式的一部分:它显示哪个 实例(即this)引发了事件。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
  • 2016-01-22
  • 2011-04-13
  • 1970-01-01
相关资源
最近更新 更多