如何修复 AddressOf 需要与委托进行轻松对话的错误
抱歉,这是 C# 和 VB.Net 的混合体
我有一个带有 2 个委托的 C# 类:
public delegate string GetSettingDelegate(string key);
public event GetSettingDelegate GetSettingEvent;
public delegate void SetSettingDelegate(string key, string value);
public event SetSettingDelegate SetSettingEvent;
在 VB 类中,我向事件添加处理程序:
AddHandler _gisCtrl.SetSettingEvent, AddressOf SetSetting
AddHandler _gisCtrl.GetSettingEvent, AddressOf GetSetting
当我尝试删除处理程序时:
RemoveHandler _gisCtrl.SetSettingEvent, AddressOf SetSetting
RemoveHandler _gisCtrl.GetSettingEvent, AddressOf GetSetting
SetSetting 正常,但 GetSetting 抛出警告:
AddressOf 表达式在此上下文中不起作用,因为 AddressOf 的方法参数需要与事件的延迟类型进行轻松的对话。
以下是方法
Private Sub SetSetting(ByVal key As String, ByVal value As String)
KernMobileBusinessLayer.[Global].Settings.SetValue(key, value)
End Sub
Private Function GetSetting(ByVal key As String)
Return KernMobileBusinessLayer.[Global].Settings.GetString(key)
End Function
知道如何解决这个问题以及为什么首先抛出它吗?这两个委托/事件/方法看起来非常相似,我不知道为什么一个可以,一个会发出警告。
Sorry, this is a mix of C# and VB.Net
I have a C# class with with 2 delegates:
public delegate string GetSettingDelegate(string key);
public event GetSettingDelegate GetSettingEvent;
public delegate void SetSettingDelegate(string key, string value);
public event SetSettingDelegate SetSettingEvent;
In a VB class I add handlers to the event:
AddHandler _gisCtrl.SetSettingEvent, AddressOf SetSetting
AddHandler _gisCtrl.GetSettingEvent, AddressOf GetSetting
When I try and remove the handlers:
RemoveHandler _gisCtrl.SetSettingEvent, AddressOf SetSetting
RemoveHandler _gisCtrl.GetSettingEvent, AddressOf GetSetting
SetSetting is OK but GetSetting throws a warning:
The AddressOf expression has no effect in this context because the method arguments to AddressOf requires a relaxed conversation to the delagate type of the event.
Here are the methods
Private Sub SetSetting(ByVal key As String, ByVal value As String)
KernMobileBusinessLayer.[Global].Settings.SetValue(key, value)
End Sub
Private Function GetSetting(ByVal key As String)
Return KernMobileBusinessLayer.[Global].Settings.GetString(key)
End Function
Any idea how to fix this and why it is thrown in the first place? The 2 delegates/events/methods look similar enough that I don't know why one is OK and one throws a warning.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您的 vb 代码:
与 C# 委托定义不匹配:
您应该在 VB 实现中指定返回类型,如下所示:
your vb code:
doesn't match the C# delegate definition:
you should specify a return type in your VB implementation, like this:
现有的答案解决了如何解决问题(以及导致问题出现的逻辑错误),但它们没有解释被警告的潜在行为或为什么需要修复它。
VB 的一个长期设计理念是更加宽松的类型,并尝试做它推断用户想要做的事情,即使严格的类型检查不允许这样做。
就代表而言,这采取“宽松代表大会”的形式。当 VB 不处于
Option Strict
模式时,它将允许分配具有“兼容”签名的委托,而不是要求完全匹配。它将通过创建具有确切签名的编译器生成的委托来填充此内容,然后调用用户提供的委托。这通常效果很好(对于“良好”的适当定义)并且对用户完全透明。它不能很好地工作的是事件订阅,更具体地说是通过
RemoveHandler
取消订阅(并且它也适用于其他一些事件库,例如某些版本的 Prism 有一个>Unsubscribe
接受Action(Of T)
作为参数,并且会遇到同样的问题)。当您使用
RemoveHandler
删除处理程序时,.NET 使用提供的委托作为键来搜索要删除的委托。这要求取消订阅的委托与订阅的委托相同。当签名匹配时,AddressOf
每次都会为相同的引用例程返回相同的委托。但是,当签名不匹配时,宽松的委托约定意味着每次都会插入一个新的编译器生成的委托,因此您用于尝试取消订阅的委托与委托不同您订阅了。该警告告诉您RemoveHandler
将不起作用,因为它找不到匹配的处理程序。如果没有发现这一点,可能会导致令人惊讶的行为,即打算取消订阅的客户端即使在应该死亡后仍继续收到事件。
我真的很惊讶你收到了警告。我在 Visual Studio 的更高版本中没有看到这一点。
根据我的经验,使用 Option Strict 是解决问题的唯一方法。打开各个警告选项但保留
Option Strict Off
会保持沉默。The existing answers address how to fix the problem (and what logic error is leading it to issue), but they don't explain the underlying behavior that is being warned about or why it needs to be fixed.
A longtime design philosophy of VB is to be more loosely typed and try to do what it infers the user wants to do even if strict type checking would disallow it.
In the case of delegates, this takes the form of the "relaxed delegate convention". When VB is not in
Option Strict
mode, it will allow assignment of a delegate with a "compatible" signature rather than requiring an exact match. It will fill this in by creating a compiler-generated delegate with the exact signature which then calls the user-provided delegate. This usually works well (for suitable definition of "well") and is completely transparent to the user.Where it does not work well is with event subscriptions, more specifically with unsubscription via
RemoveHandler
(and it also applies to some other event libraries e.g. certain version of Prism have anUnsubscribe
which takes anAction(Of T)
as an argument and is subject to the same problem).When you remove a handler using
RemoveHandler
, .NET searches for the delegate to remove by using the supplied delegate as a key. This requires that the delegate unsubscribed be identical to the delegate that is subscribed. When signatures match,AddressOf
will return the same delegate for the same referenced routine every time. However, when signatures do not match, the relaxed delegate convention means that a new compiler-generated delegate is inserted every time, so the delegate that you use to try to unsubscribe is different from the delegate that you subscribed. The warning is telling you that theRemoveHandler
will have no effect because it will not find a matching handler.If this isn't caught, it can cause surprising behavior where intended-to-be unsubscribed clients continue to get events even after they're supposed to be dead.
I'm actually surprised you got a warning. I didn't see one in later versions of Visual Studio.
In my experience, using
Option Strict
is the only way to catch the problem. Turning on the individual warning options but leavingOption Strict Off
is silent.可能您的 GetSetting 函数必须完全匹配 GetSettingDelegate 签名:
probably your
GetSetting
function must fully matchGetSettingDelegate
signature: