gpt4 book ai didi

c# - 编译器生成的事件的支持字段是否始终保证使用与事件相同的名称?

转载 作者:太空狗 更新时间:2023-10-29 17:35:08 25 4
gpt4 key购买 nike

C# 允许我们 to create custom event accessors .

Action _custom;
public event Action Custom
{
add { _custom = (Action)Delegate.Combine( _custom, value ); }
remove { _custom = (Action)Delegate.Remove( _custom, value ); }
}

如果您不指定它们,the compiler creates them for you . C# 语言规范:

When compiling a field-like event, the compiler automatically creates storage to hold the delegate, and creates accessors for the event that add or remove event handlers to the delegate field.

使用dotPeek反编译的源代码对于一个简单的 public 事件 Action Public; 看起来如下:

  private Action Public;

public event Action Public
{
add
{
Action action = this.Public;
Action comparand;
do
{
comparand = action;
action = Interlocked.CompareExchange<Action>(
ref this.Public, comparand + value, comparand);
}
while (action != comparand);
}
remove
{
Action action = this.Public;
Action comparand;
do
{
comparand = action;
action = Interlocked.CompareExchange<Action>(
ref this.Public, comparand - value, comparand);
}
while (action != comparand);
}
}

值得注意的是,字段和事件使用相同的名称。这导致了some people得出结论,您可以通过在类中查找与事件同名的字段来找到有关反射期间支持字段的信息。我按如下方式实现了这一点:

public static FieldInfo GetFieldInfo( this EventInfo eventInfo )
{
Contract.Requires( eventInfo != null );

return eventInfo.DeclaringType.GetField(
eventInfo.Name,
BindingFlags.DeclaredOnly | BindingFlags.Instance |
BindingFlags.Public | BindingFlags.NonPublic );
}

这可行,但提出了一个问题:编译器生成的事件的支持字段是否始终保证使用与事件相同的名称?

无法使用 Visual Studio 创建自定义事件访问器来访问具有相同名称的委托(delegate)。这导致消息:“已声明具有相同名称的成员。”我想知道您是否可以得出结论,任何没有可用的具有相同名称的支持委托(delegate)的事件都是具有自定义的事件访问器。

最佳答案

Is the backing field of a compiler generated event always guaranteed to use the same name as the event?

Jon 和 Marc 的回答“否”是完全正确的。

这是一个未记录的编译器实现细节,规范中明确注明,随时可能更改。

在实践中,这不太可能改变。我们使用字段和事件具有相同名称这一事实作为在编译器中将它们在逻辑上相互关联的最简单可能方式。

It's not possible to create custom event accessors which access a delegate with the same name using Visual Studio. This results in the message: "Member with the same name is already declared."

正确。

I am wondering whether you could conclude that any event for which no backing delegate with the same name is available is an event with custom accessors.

我不太愿意做出这样的结论。如果您知道有问题的程序集是从 C# 编译器发出的,您可能能够得出该结论。但就发射组件而言,我们并不是唯一的游戏。您可以使用 ILDASM 做一些非常奇怪的事情。

请问你为什么想知道这些东西?我同意马克;如果你通过反射访问一个字段,你可能做错了。您应该能够毫无问题地访问类内的字段(因为它只是一个私有(private)字段),并且从类外,您没有业务查看另一个类的私有(private)实现细节。 使用反射来绕过访问器强加的线程安全性是特别过分的。那些访问器是为了保护你;不要绕着他们跑。

关于c# - 编译器生成的事件的支持字段是否始终保证使用与事件相同的名称?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9847424/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com