3

在 .NET 中,如果我正在实现一个包含事件的接口,但该事件对我的对象没有意义(假设它是一个更改事件并且我正在编写一个不可变对象),那么我可以只为addremove-- 一个空实现。这避免了为我永远不会使用的委托字段分配存储空间,也避免了“事件从不使用”编译器警告,所以这是一个全面的胜利。

public event EventHandler Changed {
    add {}
    remove {}
}

当我在 WinRT 类(从 FrameworkElement 继承)中尝试相同的事情时,我在访问器上收到编译器错误add:“并非所有代码路径都返回值”。

如何从add访问器返回值?它应该返回什么?

更新:显然这个问题只适用于 WinRT 事件(例如,如果你正在实现一个包含事件的 WinRT 接口)。如果您正在编写一个普通的旧 CLR 事件,则上述语法有效。

4

2 回答 2

6

我在 Windows 开发中心找到了这篇文章。似乎addandremove访问器功能确实随着 Metro 发生了变化:

.NET Framework 对 Windows 运行时的支持通过隐藏 Windows 运行时事件模式和 .NET Framework 事件模式之间的差异,可以轻松地在 Windows 运行时组件中声明事件。但是,当您在 Windows 运行时组件中声明自定义事件访问器时,您必须遵循 Windows 运行时模式。

当您注册以处理 Windows 运行时中的事件时,添加访问器会返回一个令牌。要取消注册,请将此令牌传递给删除访问器。这意味着 Windows 运行时事件的添加和删除访问器与您习惯的访问器具有不同的签名。

幸运的是,Visual Basic 和 C# 编译器简化了此过程:当您在 Windows 运行时组件中使用自定义访问器声明事件时,编译器会自动使用 Windows 运行时模式。例如,如果您的 add 访问器未返回令牌,您会收到编译器错误。

.NET Framework 提供了两种类型来支持实现:

  • EventRegistrationToken 结构表示令牌。
  • EventRegistrationTokenTable<T> 类创建令牌并维护令牌和事件处理程序之间的映射。泛型类型参数是事件参数类型。您为每个事件创建一个此类的实例,第一次为该事件注册事件处理程序。
于 2012-06-19T11:24:10.660 回答
4

因此,根据 Anders发布的链接,访问器似乎add需要返回一个EventRegistrationToken. EventRegistrationToken只是一个结构,显然没有字段,并且没有超出默认值的构造函数,所以看起来我可以无害地new向上 - 特别是因为唯一会使用它的代码是 my remove,这并不在乎。

因此,null 事件的 WinRT 等效项似乎是:

public event EventHandler Changed {
    add { return new EventRegistrationToken(); }
    remove {}
}
于 2012-06-19T11:42:12.717 回答