1

I have some C# code that I am converting to VB.NET.

In a class I have the following:

public class ServiceCapServerLib : ICapServerLib
{
    private readonly dynamic _lib;

    public void AddMessageReceivedHandler(ICapServerLib.MessageReceivedEventHandler action)
    {
        _lib.MessageReceived += action;
    }
}

My VB Equivalent of this should be:

Option Strict Off

Public Class ServerCapServerLib
    Implements ICapServerLib

    Private ReadOnly _lib As Object

    Public Sub AddMessageReceivedHandler(ByVal action As ICapServerLib.MessageReceivedEventHandler) Implements ICapServerLib.AddMessageReceivedHandler
        AddHandler _lib.MessageReceived, action
    End Sub
End Class

But it fails to compile with "MessageReceived is not a member of Object". This is obviously the case but the C# code works, so am I missing something?

EDIT: I also tried AddHandler _lib.MessageReceived, AddressOf action but this gives the error "'AddressOf' operand must be the name of a method (without parentheses)"

Matt Wilko
  • 26,994
  • 10
  • 93
  • 143
  • 1
    I would consider using an interface, not use any `dynamic`. – Daniel A. White Sep 23 '15 at 15:54
  • 1
    Why are you using dynamic for that in the first place? – mason Sep 23 '15 at 15:56
  • I have to use dynamic because it is utilising late binding on a COM component – Matt Wilko Sep 23 '15 at 15:57
  • Almost duplicate - [VB.Net equivalent for C# 'dynamic' with Option Strict On](http://stackoverflow.com/questions/2889974/vb-net-equivalent-for-c-sharp-dynamic-with-option-strict-on) – Alexei Levenkov Sep 23 '15 at 15:57
  • 1
    **Stop moving the goalposts, please** – Ben Voigt Sep 23 '15 at 15:59
  • @BenVoigt - apologies I was trying to make things clearer. Hopefully that is now – Matt Wilko Sep 23 '15 at 16:01
  • 1
    @AlexeiLevenkov - not really a dupe at all because I am happy to use Option Strict Off. In fact you have to use Late Binding – Matt Wilko Sep 23 '15 at 16:05
  • 2
    VB.NET never did have support for late-binding events. Reflection isn't going to help here either, you'll want to keep this code in a C# class library. – Hans Passant Sep 23 '15 at 17:21
  • Thanks @HansPassant - When you say something I take it to the bank. – Matt Wilko Sep 24 '15 at 07:52
  • Just remove the `AddressOf`. VB uses `AddressOf` to create a delegate instance from the name of a function. But the identifier `action` names a parameter, which *already is a delegate*. NB: Parentheses seem to be coming and going from the question as it is revised. They shouldn't be used, either, just like the C# version doesn't have them. – Ben Voigt Sep 23 '15 at 15:57

1 Answers1

2

What you are trying is not valid because the underlying assumption (dynamic in C# is the same than object in VB.NET with Option Strict Off) is not exactly right.

dynamic in C#:

The dynamic type enables the operations in which it occurs to bypass compile-time type checking. Instead, these operations are resolved at run time.

For Visual Studio, dynamic variables can be anything and that's why it will never complain about a given property (or event, like in this case). Your first code is fine because it accepts that _lib has an event called MessageReceived (no check is performed).


Option Strict Off in VB.NET:

(when On) Restricts implicit data type conversions to only widening conversions, disallows late binding, and disallows implicit typing that results in an Object type.

What means that, with Option Strict Off, Visual Studio "complains less" in certain situations. To understand the exact implications of the aforementioned not-too-accurate statement, you can either analyse in depth the exact definition of each scenario (e.g., early & late binding) or believe what Visual Studio tells you. Independently upon the option you choose, you will come to the conclusion that, in this specific situation, _lib has to be casted/converted to the corresponding type (ICapServerLib) before bringing the event into picture.


Note that .NET 4.0 introduced the System.Dynamic namespace (at the same time than C# dynamic). Both VB.NET & C# can deal with the contents of this namespace without any restriction (e.g., https://msdn.microsoft.com/en-us/library/ee461504(v=vs.110).aspx).

I don't have too much experience with the aforementioned namespace and am not sure whether you can perfectly emulate the C# dynamic behaviour in VB.NET. But I am certain about something: Option Strict Off + Object is not the same than dynamic in C#. Also note that the VB.NET WithEvents does not exist in C# and that's why in VB.NET events are treated differently than other properties (unlikely in C#).


NOTE: Hans Passant has written a comment to this question highlighting that late-binding events have never been supported by VB.NET. I am not in a position to (fully) confirm/dismiss such a statement, but will assume that it is right. In that case, the intended direct conversion of the original C# code to VB.NET is not possible.

varocarbas
  • 12,354
  • 4
  • 26
  • 37
  • Thanks I tried that exact code but I still get the error "MessageReceived is not a member of object" – Matt Wilko Sep 24 '15 at 07:24
  • Yes I tried the exact code you posted: http://www.tiikoni.com/tis/view/?id=43ba972 – Matt Wilko Sep 24 '15 at 07:31
  • @MattWilko I have done some tests with no positive result. I have updated my answer to reflect this issue (and the place where you might find something. System.Dynamic namespace). Note that events are treated slightly different in C# & VB.NET (requiring `WithEvents`) and you would also have to account for this issue. – varocarbas Sep 24 '15 at 08:12
  • 1
    @MattWilko I have realised right now that Hans Passant has written a comment above saying that what you are trying to accomplish is not possible in VB.NET. He might be wrong (like everyone), but a so generic statement coming from a so experienced person is quite likely to be true. – varocarbas Sep 24 '15 at 08:36