如何修复 AddressOf 需要与委托进行轻松对话的错误

发布于 2024-11-09 21:29:16 字数 1138 浏览 4 评论 0原文

抱歉,这是 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

困倦 2024-11-16 21:29:17

您的 vb 代码:

Private Function GetSetting(ByVal key As String)

与 C# 委托定义不匹配:

public delegate string GetSettingDelegate(string key);

您应该在 VB 实现中指定返回类型,如下所示:

Private Function GetSetting(ByVal key As String) As String

your vb code:

Private Function GetSetting(ByVal key As String)

doesn't match the C# delegate definition:

public delegate string GetSettingDelegate(string key);

you should specify a return type in your VB implementation, like this:

Private Function GetSetting(ByVal key As String) As String
掩耳倾听 2024-11-16 21:29:17

现有的答案解决了如何解决问题(以及导致问题出现的逻辑错误),但它们没有解释被警告的潜在行为或为什么需要修复它。

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 an Unsubscribe which takes an Action(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 the RemoveHandler 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 leaving Option Strict Off is silent.

爱她像谁 2024-11-16 21:29:16

可能您的 GetSetting 函数必须完全匹配 GetSettingDelegate 签名:

Private Function GetSetting(ByVal key As String) as String

probably your GetSetting function must fully match GetSettingDelegate signature:

Private Function GetSetting(ByVal key As String) as String
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文