使用=而不是+ =订阅事件

时间:2015-07-05 02:35:24

标签: c# events

使用

订阅活动是否有任何问题
MyPopup.CustomPopupPlacementCallback += popupFixCentered;

而不是:

namespace DataAccessLayer
{

    public class DAL : DbContext
    {
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Entity<Administrator>().ToTable("tblAdministrator");
            modelBuilder.Entity<User>().ToTable("tblUser");
        }

        public DbSet<Administrator> Administrators { get; set; }

        public DbSet<User> Users { get; set; }
    }
}

例如,如果我要从另一个方法更改为不同的回调,我想确保只订阅一个回调而不需要 - =正确的回调。

2 个答案:

答案 0 :(得分:4)

嗯,听起来你没有尝试过。如果您这样做,您将收到以下编译错误:

  

事件'XXX'只能出现在+ =或 - =的左侧(除非在'YourClass'类型中使用)

错误非常明确:您只能在活动中使用+=-=运算符。

如果您尝试从定义事件的类 中分配event,那么它将“正常”。但在这种情况下它似乎能够分配给event的原因是因为它实际上没有访问该事件。它正在访问一个您可能没有意识到的自动生成的私有委托实例。

Chris Burrows' article引用主题:

  

在定义类似字段的事件E的类或结构之外,绑定到名称E解析为事件本身,唯一合法的操作是调用访问器;在定义类字段事件E的类或结构内部,绑定到名称E解析为私有委托字段。

要理解这一点,您需要在定义事件时可视化,例如:

public event EventHandler MyEvent;

...你看不到的是,它实际上被翻译成类似的东西(我正在从Jon Skeet's article on events and delegates复制它。还要注意它被翻译成的确切代码有在C#版本之间进行了更改,因此可能会有所不同,但总体思路是相同的)

private EventHandler _myEvent;

public event EventHandler MyEvent
{
    add
    {
        lock (this)
        {
            _myEvent += value;
        }
    }
    remove
    {
        lock (this)
        {
            _myEvent -= value;
        }
    }        
}

因此,当您从 外部 类访问MyEvent时,您只能通过以下方法调用addremove方法+=-=运营商。

但是从 类中,访问MyEvent意味着不同的东西。它实际上成为您无法看到的私有_myEvent委托变量的引用,但它就在那里。因为这是委托类型,所以您可以在其上使用赋值(=)运算符。

因此,要实现您想要的功能,您可以在定义事件的同一个类中定义一个公共方法,并使用该方法设置新的事件处理程序。

这样的事情:

public class MyClass
{
    public event EventHandler MyEvent;

    public void setSingleEventHandler(EventHandler eventHandler)
    {
        this.MyEvent = eventHandler;
    }
}

但如果你要这样做,那么它就会失去event类型的目的。如果您只想在任何给定时间调用单个事件处理程序,那么以这种方式定义它(不使用event关键字)更有意义:

public class MyClass
{
    public EventHandler MyEvent { get; set; }
}

<强>参考

Jon Skeet文章:Delegates and Events

Chris Burrows文章:(另请参阅本系列的其余部分):Events get a little overhaul in C# 4, Part II: Semantic Changes and +=/-=

答案 1 :(得分:0)

我刚试过它。是的,您可以使用=运算符分配给事件。 (编辑:显然只来自同一个班级)

delegate void Foo();
event Foo bar;
Method()
{
    bar = () => { Console.WriteLine("1"); };
    bar();
    bar = () => { Console.WriteLine("2"); };
    bar();
}

产生输出:

1
2

但是如果你尝试从课外分配,它会给你一个错误。

您可以使用java风格的set方法来解决这个问题:

SetBar(Foo foo)
{
    bar = foo;
}  

只有我推荐使用java约定来进行属性的外部访问:)