簡體   English   中英

C#:什么是虛擬事件以及如何使用它們?

[英]C#: What are virtual events and how can they be used?

虛擬活動如何運作? 你會如何覆蓋它? 這將如何運作? 在什么情況下你會這樣做?

例如,它可以替代受保護的 OnEvent 方法嗎? 那么繼承類可以覆蓋事件並直接引發它嗎? 或者那會是錯誤的還是行不通的?

MSDN 是這樣說的:

可以使用 virtual 關鍵字將事件標記為虛擬事件。 這使派生類能夠使用 override 關鍵字覆蓋事件行為。 覆蓋虛擬事件的事件也可以被密封,它指定對於派生類它不再是虛擬的。

但這並沒有讓我變得更聰明。 密封的東西很明顯。

注意:我已經看過C# 中的虛擬事件如何工作? 問題,但這並不是關於虛擬事件的工作原理。 而是那個人如何獲得他從使用它們中得到的結果。 試圖從他的例子和答案中找出虛擬事件是什么,但無法真正理解它。

虛擬事件只是一個可以在派生類中覆蓋的事件。

您對虛擬財產的概念感到滿意,可以覆蓋 getter 和 setter 嗎? 如果是這樣,您可以以完全相同的方式考慮虛擬事件:不是 getter 和 setter,而是“添加”操作和“刪除”操作。 這些可以是虛擬的,因此可以多態處理。 您可以像實現任何其他虛擬/覆蓋成員一樣實現它們。

例子:

using System;

class Base
{
    public virtual event EventHandler Foo
    {
        add
        {
            Console.WriteLine("Base Foo.add called");
        }
        remove
        {
            Console.WriteLine("Base Foo.remove called");
        }
    }
}

class Derived : Base
{
    public override event EventHandler Foo
    {
        add
        {
            Console.WriteLine("Derived Foo.add called");
        }
        remove
        {
            Console.WriteLine("Derived Foo.remove called");
        }
    }
}

class Test
{
    static void Main()
    {
        Base x = new Derived();

        x.Foo += (sender, args) => {};
    }
}

請注意,事件本身不對引發時發生的事情負責 - 只是添加/刪除方面。 (無論如何,在 C# 中;CLR 本身有提升的概念,但我們暫時忽略它。)

如果您對事件和委托之間的區別有點模糊,您可能還想閱讀我關於事件的文章

就個人而言,我發現我想要一個虛擬活動是非常罕見的。

另請注意,在 C# 中,派生類無法觸發純粹在基類中定義的事件(無論它具有什么修飾符)。 因此,我們需要為派生類創建一個新事件或覆蓋事件,並且在大多數情況下,如果要觸發相同的事件,則首選覆蓋事件。

對於要提出的Foo ,我發現已接受的答案中缺少 2 個替代方案。

public class Base 
{
    public virtual event EventHandler Foo;

    public void Bar()
    {
        RaiseFoo();
    }

    protected virtual void RaiseFoo()
    {
        Foo?.Invoke(this, EventArgs.Empty);
    }
}

public class Derived : Base
{
    // In this case we use the base Foo as a backing store.
    public override event EventHandler Foo
    {
        add { base.Foo += value; }
        remove { base.Foo -= value; }
    }
}

public class Derived2 : Base
{
    public override event EventHandler Foo;

    // In this case we raise the overriden Foo.
    protected override void RaiseFoo()
    {
        Foo?.Invoke(this, EventArgs.Empty);
    }
}

class Test
{
    static void Main()
    {
        Base x = new Derived();
        x.Foo += (sender, e) => { };
        x.Bar();
        Base x2 = new Derived2();
        x2.Foo += (sender, e) => { };
        x2.Bar();
    }
}

請注意,這不起作用:

public class Derived3 : Base
{
    public override event EventHandler Foo
    {
        add { base.Foo += value; }
        remove { base.Foo -= value; }
    }

    protected override void RaiseFoo()
    {
        Foo?.Invoke(this, EventArgs.Empty);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM