How fix AddressOf requires a relaxed conversation to the delegate error
Asked Answered
P

3

7

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.

Pneumatology answered 23/5, 2011 at 22:56 Comment(2)
GetSetting(), as defined above, would return Object, not String. I think max has it right.Malamute
Use Option Strict On to let the compiler catch these kind of mistakes.Frenzy
B
16

probably your GetSetting function must fully match GetSettingDelegate signature:

Private Function GetSetting(ByVal key As String) as String
Bilocular answered 23/5, 2011 at 23:4 Comment(1)
Thanks. Obvious now! I marked yours as the answer as you answered first.Pneumatology
A
7

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
Almena answered 23/5, 2011 at 23:6 Comment(0)
B
0

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.

Boatsman answered 9/8 at 22:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.