我们可以创建一个不像现场的事件吗?
Can we create an event that isn't field-like?
在深入了解 C# 中,Jon Skeet 指出:
Developers often confuse events and delegate instances, or events and fields declared with delegate types.
看了他的解释,我明白了很多,虽然我仍然对事件到底是什么感到困惑。从下面的代码来看,一个事件所做的一切似乎都是为了限制一个 class 必须对另一个 class 中的字段进行委托的访问权限。
... you often don't want code outside a class to be able to arbitrarily change (or call) the handlers for an event... [so] the compiler turns the declaration into both an event with default add/remove implementations and a private field of the same type.
换句话说,事件与委托的区别在于访问控制。或者这仅适用于 Jon 所说的 "field-like events"?
- 场式事件与事件有区别吗?
- C# 中的事件总是类字段的吗?还是我们也可以创建非类字段的事件?
- 事件和类场事件之间有什么区别(如果有)?
换句话说,C# 是否同时支持事件和类似字段的事件,或者这两种表达方式是否相同?
此处的代码示例https://dotnetfiddle.net/7fOwvb
using System;
using System.Reflection;
public delegate void TheDelegate(string message);
public static class Program
{
public static event TheDelegate TheEvent;
public static TheDelegate DelInstance;
public static void Main()
{
DelInstance = new TheDelegate(TheMethod);
DelInstance += TheMethod;
DelInstance.Invoke("Invoke the delegate.");
PrintMemberInfo(DelInstance.GetType());
TheEvent += TheMethod;
TheEvent += TheMethod;
TheEvent.Invoke("Invoke the event.");
PrintMemberInfo(TheEvent.GetType());
new AnotherClass();
}
// Create a method for a delegate.
public static void TheMethod(string message)
{
Console.WriteLine(message);
}
public static void PrintMemberInfo(System.Type t)
{
foreach (MemberInfo m in t.GetMembers())
{
Console.Write(m.Name + ", ");
}
Console.WriteLine("\n");
}
}
public class AnotherClass
{
public AnotherClass()
{
Program.DelInstance += new TheDelegate(AnotherMethod);
Program.DelInstance.Invoke("Another class");
// Error... we can only call += or -+
// Program.TheEvent.Invoke();
}
public void AnotherMethod(string message)
{
Console.WriteLine(message);
}
}
类字段事件是等同于自动 属性 的事件,即编译器生成 add
/remove
访问器的事件。
Field-like events
Within the program text of the class or struct that contains the declaration of an event, certain events can be used like fields. To be used in this way, an event must not be abstract or extern, and must not explicitly include event-accessor-declarations. Such an event can be used in any context that permits a field. The field contains a delegate (§15) which refers to the list of event handlers that have been added to the event. If no event handlers have been added, the field contains null.
(C# 5.0 specification)
您可以在 C# 中使用自定义访问器(add
和 remove
)实现事件。
event EventHandler IDrawingObject.OnDraw
{
add
{
...
}
remove
{
...
}
}
参见 How to: Implement Custom Event Accessors (C# Programming Guide)。
在深入了解 C# 中,Jon Skeet 指出:
Developers often confuse events and delegate instances, or events and fields declared with delegate types.
看了他的解释,我明白了很多,虽然我仍然对事件到底是什么感到困惑。从下面的代码来看,一个事件所做的一切似乎都是为了限制一个 class 必须对另一个 class 中的字段进行委托的访问权限。
... you often don't want code outside a class to be able to arbitrarily change (or call) the handlers for an event... [so] the compiler turns the declaration into both an event with default add/remove implementations and a private field of the same type.
换句话说,事件与委托的区别在于访问控制。或者这仅适用于 Jon 所说的 "field-like events"?
- 场式事件与事件有区别吗?
- C# 中的事件总是类字段的吗?还是我们也可以创建非类字段的事件?
- 事件和类场事件之间有什么区别(如果有)?
换句话说,C# 是否同时支持事件和类似字段的事件,或者这两种表达方式是否相同?
此处的代码示例https://dotnetfiddle.net/7fOwvb
using System;
using System.Reflection;
public delegate void TheDelegate(string message);
public static class Program
{
public static event TheDelegate TheEvent;
public static TheDelegate DelInstance;
public static void Main()
{
DelInstance = new TheDelegate(TheMethod);
DelInstance += TheMethod;
DelInstance.Invoke("Invoke the delegate.");
PrintMemberInfo(DelInstance.GetType());
TheEvent += TheMethod;
TheEvent += TheMethod;
TheEvent.Invoke("Invoke the event.");
PrintMemberInfo(TheEvent.GetType());
new AnotherClass();
}
// Create a method for a delegate.
public static void TheMethod(string message)
{
Console.WriteLine(message);
}
public static void PrintMemberInfo(System.Type t)
{
foreach (MemberInfo m in t.GetMembers())
{
Console.Write(m.Name + ", ");
}
Console.WriteLine("\n");
}
}
public class AnotherClass
{
public AnotherClass()
{
Program.DelInstance += new TheDelegate(AnotherMethod);
Program.DelInstance.Invoke("Another class");
// Error... we can only call += or -+
// Program.TheEvent.Invoke();
}
public void AnotherMethod(string message)
{
Console.WriteLine(message);
}
}
类字段事件是等同于自动 属性 的事件,即编译器生成 add
/remove
访问器的事件。
Field-like events
Within the program text of the class or struct that contains the declaration of an event, certain events can be used like fields. To be used in this way, an event must not be abstract or extern, and must not explicitly include event-accessor-declarations. Such an event can be used in any context that permits a field. The field contains a delegate (§15) which refers to the list of event handlers that have been added to the event. If no event handlers have been added, the field contains null.
(C# 5.0 specification)
您可以在 C# 中使用自定义访问器(add
和 remove
)实现事件。
event EventHandler IDrawingObject.OnDraw
{
add
{
...
}
remove
{
...
}
}
参见 How to: Implement Custom Event Accessors (C# Programming Guide)。