【问题标题】:Why unused event arguments require assignment?为什么未使用的事件参数需要赋值?
【发布时间】:2013-01-30 07:54:22
【问题描述】:

根据C# Reference

"null 关键字是一个字面量,表示一个空引用,一个 那不涉及任何对象。 null 是的默认值 引用类型变量'

我很惊讶地发现
在以下应用代码中注释e=null 行(取自文章"Difference Between Events And Delegates in C#")会导致编译错误:

Use of unassigned local variable 'e'

虽然没有注释,但它被编译并运行。

我不明白:

  • 变量e在哪里使用?
  • 是否可以在不将变量分配给null 的情况下强制应用程序运行?

f

using System;   
class Program   
{   
  static void Main(string[] args)   
  {   
    DelegatesAndEvents obj = new DelegatesAndEvents();   
    obj.Execute();  
  }  
}  
public class DelegatesAndEvents  
{
  public event EventHandler MyEvent;
  internal void Execute()
  {
    EventArgs e;
//Commenting the next line results in compilation error
//Error 1   Use of unassigned local variable 'e'
    e = null;
    int sender = 15;
    MyEvent += MyMethod;
    MyEvent += MyMethod2;
    MyEvent(sender, e);
  }
  void MyMethod(object sender, EventArgs e)
  {
    Console.WriteLine(sender);
  }
  void MyMethod2(object sender, EventArgs e)
  {
    Console.WriteLine(sender);
    Console.ReadLine();
  }
}

更新(或对所有答案的评论):
所以,我从来不知道,有一种空值 - 一个已分配,另一个未分配......有趣......

他们可能应该有不同的类型,用于检查:
如果 typeof(unassigned-null) 则执行此操作;
如果 typeof(assigned_null) 则执行此操作;

【问题讨论】:

  • 查看 Eric 和 Mark 对非常相似的问题的回答 stackoverflow.com/questions/1423437/…stackoverflow.com/questions/8931226/…
  • The reason this is illegal in C# is because using an unassigned local has high likelihood of being a bug - Eric Lippert(来自上面的链接)
  • e 用于MyEvent(sender, e) 行。编译器不会进行全面分析以确定所有订阅者都忽略了e 参数。 (谁知道呢。既然是公开活动,可能其他人订阅了MyEvent,而其他人使用了e。)
  • 不,没有两种空值。您只是在处理 C# 的明确分配规则 - 即您可能 从尚未分配值的局部变量中读取。这超出了 CLR 的要求(确保任何引用变量在第一次赋值之前都是 null)。因为,正如@asawyer 在他们的评论中指出的那样,忘记赋值是错误的常见来源。
  • @Damien_The_Unbeliever,那是个笑话

标签: c# events delegates event-handling arguments


【解决方案1】:

回答您的问题:

  • 问题:变量e在哪里使用?

Answer: 用于传递给 MyEvent(sender, e);

  • 问题:是否可以强制应用程序运行而无需将变量分配为空值?

答案:不,这并不愚蠢,因为您通过将 e 传递给另一个方法来使用它。您只是没有直接使用它 - 但您仍在使用它。

实际上,您不需要在任何地方声明 e - 您可以直接将 null 传递给 MyEvent:

MyEvent(sender, null);

那么你就不需要做任何多余的变量声明了。

【讨论】:

  • 你也可以使用EventArgs.Empty,而不是null,如果消费者调用Equals或实例成员,这不会失败。题外话,但无论如何值得一提,恕我直言。
【解决方案2】:

您正在使用e 而不为其分配值。使用e = null;,您正在为变量 e 赋值,因为 null 也是一个值

此外,根据 C#,引用类型的引用默认值为 null,但这里 e 是一个变量。变量没有默认值,在使用之前必须有“明确的赋值”。

【讨论】:

  • 调试器告诉我,在将变量 e 赋值为 null 之前,它也是 null...或者它是什么?
  • @Fulproof 调试器将向您显示许多不在范围内的事物的价值,或者由于某种原因在代码中不具有技术访问价值。它只是查看当时内存中的内容,然后将它们吐回给你。
【解决方案3】:

在编译Execute 时,编译器无法知道哪些事件处理程序注册到MyEvent。 (其他人可能在调用Execute 之前已经注册,他们可能会尝试使用e)。因此,它不会尝试对它可能知道已注册的任何处理程序进行任何分析。所以,既然要传递e,就必须初始化。

如果你想通过null,为什么要引入e呢?只要有

MyEvent(sender, null);

这至少使您的意图明确。

【讨论】:

  • 真的,我的意图是我目前正在搜索代码示例,以说明为什么我不得不总是有事件参数。我什至不知道何时以及为什么总是需要它们
  • @Fulproof Uhh....您正在重用特定的委托类型,EventHandler。如果你不喜欢它的参数,使用不同的委托类型。
  • @Fulproof - 它们并不总是需要 - 但它们是推荐模式的一部分,因为经常观察到处理程序想要访问到发生事件的对象(它们可能正在侦听多个对象),并且事件通常具有“事件发生”之外的附加信息要传达给处理程序。
  • @asawyer,来自Difference Between Events And Delegates 的这个问题,其中明确的委托最初参与但未使用,并且无根据的 EventArgs var 仍然存在
  • @Damien_The_Unbeliever,我真正的问题是了解 EventArgs 的使用,我见过的所有代码和代码示例都没有使用它。我没有问只是因为我害怕它要么被欺骗要么愚蠢或太明显......
【解决方案4】:

局部变量不使用它们的默认值初始化,而字段是。

【讨论】:

  • 嗯,有道理,因为本地 var 无法从外部访问。将 e 更改为字段/属性,应用程序开始运行,无需(显式)分配给 null
猜你喜欢
  • 2010-09-14
  • 2021-10-12
  • 1970-01-01
  • 2019-11-04
  • 2023-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-16
相关资源
最近更新 更多