有一個讀通過How to: Publish Events that Conform to .NET Framework Guidelines關於如何創建和使用事件的更多信息。這個例子還不夠清楚,所以我會在這裏介紹一下這個過程。
定義事件的第一部分是要使用的事件處理程序委託。這是所有希望收到有關此事件通知的人需要的方法簽名。您通常不必自己創建新委託,您應該使用現有的EventHandler
(或通用EventHandler<TEventArgs>
)委託。如果您不需要包含有關該事件的任何其他參數,則可以使用非通用版本。否則,你會使用通用版本。在你的情況下,沒有任何關於該事件的其他論據,所以你應該使用非通用的EventHandler
。 (如果你希望能夠包含舊值和新值等信息作爲參數,你可以使用泛型版本,其中包含從EventArgs
派生的適當類。有一些高級主題,所以我們將跳過那。)
接下來的部分是定義事件。這就像爲你的課堂定義一個屬性一樣簡單。這裏的區別在於,您將使用event
關鍵字來指定您正在定義事件,然後是要使用的委託和事件的名稱。命名事件以更改屬性的慣例通常採用PropertyNameChanged
格式。由於您想要在Name
屬性發生更改時觸發事件,因此應將其命名爲:NameChanged
。
public event EventHandler NameChanged;
一個可選(但是強烈推薦)步驟是定義用於引發事件的方法。這可以讓您更容易地在需要時舉辦活動。通常的命名約定與事件命名方式類似。這一次,OnEventName
。所以你在這裏將它命名爲OnNameChanged
。它通常被定義爲一種受保護的虛擬方法,派生類可以很容易地覆蓋這個方法。函數的參數應該是事件所需的參數。由於這裏沒有參數,所以在簽名中可能沒有參數。
有了這一切,這只是一個調用事件處理程序的問題。這只是一個代表,所以只需要調用它。但是,不要忘記先檢查它是否是null
,這意味着沒有事件處理程序被註冊。處理程序的參數應該是this
(引發事件的對象)以及參數應該是什麼。在這種情況下,沒有參數,但應返回「空」EventArgs
的實例。
protected virtual void OnNameChanged()
{
EventHandler nameChanged = NameChanged; // always a good idea to store in a local variable
if (nameChanged != null)
{
nameChanged(this, new EventArgs());
}
}
最後一部分是在你的屬性,以這樣組裝起來。如果任務會改變財產的價值,你會想要舉辦活動。很簡單,只需檢查舊值是否與新值不同。如果是,請更改並提高事件。否則,別的什麼都別做。
private string name;
public string Name
{
get { return name; }
set
{
if (!String.Equals(value, name)) // if the value gets changed...
{
name = value;
OnNameChanged(); // raise the event!!!
}
}
}
現在,我們已經設置完畢的情況下,你要能夠註冊一些處理此事件。爲了能夠做到這一點,首先我們需要Person
的實例,我們希望等待Name
更改,並且我們需要事件處理方法以及事件的正確簽名。該事件被定義爲使用EventHandler
委託,因此我們需要一個簽名爲:void NameChanged(object sender, EventArgs e)
的方法。請記住,sender
參數是引發事件的對象。在這種情況下,它是一個Person
對象,所以我們可以獲取更改的對象並在需要時檢查屬性。你可以任意命名。我個人的模式是:InstanceName_EventName
。所以在這種情況下,我會命名它:person_NameChanged
。
static void person_NameChanged(object sender, EventArgs e)
{
Person person = (Person)sender; // cast back to a Person so we can see what's changed
Console.WriteLine("The name changed!");
Console.WriteLine("It is now: " + person.Name); // let's print the name
}
定義好之後,將處理程序添加到事件中,如果發生任何更改,我們會通知您。
person.NameChanged += person_NameChanged;
如果您希望處理程序完全在類中,您可以在類中註冊該事件。無需從外部連線。你可以從構造函數中完成。我不會建議將你的代碼添加到OnNameChanged()
事件引發方法中,該方法應該僅用於提升事件。
public Person(string name = "John")
{
this.name = name;
this.NameChanged += builtin_NameChanged;
}
private static void builtin_NameChanged(object sender, EventArgs e)
{
Person person = (Person)sender; // cast back to a Person so we can see what's changed
Console.WriteLine("The name changed!");
Console.WriteLine("It is now: " + person.Name); // let's print the name
}
請注意,在此特定示例中,處理程序是靜態的,因此它不受限於單個實例。它一般適用於任何Person
。請注意,由於它是靜態的,因此您無法在方法中使用this
,這就是爲什麼需要對發件人進行強制轉換的原因。最終是否是靜態的,無論哪種方式都應該沒問題。
所以把這個都在一起,這是你可以做什麼:
class Person
{
public Person(string name = "John")
{
this.name = name;
this.NameChanged += builtin_NameChanged;
}
public string Name
{
get { return name; }
set
{
if (!String.Equals(value, name))
{
name = value;
OnNameChanged();
}
}
}
public event EventHandler NameChanged;
protected virtual void OnNameChanged()
{
EventHandler nameChanged = NameChanged;
if (nameChanged != null)
{
nameChanged(this, new EventArgs());
}
}
private static void builtin_NameChanged(object sender, EventArgs e)
{
Person person = (Person)sender;
Console.WriteLine("The name changed!");
Console.WriteLine("It is now: " + person.Name);
}
private string name;
}
class Program
{
static void Main(string[] args)
{
Person person = new Person();
person.Name = "Paul";
}
}