Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# to VB.Net: Why does this fail to compile when converted to VB?

I have this C# extension method that will extend any dictionary where the Value type is an IList. When I write the equivalent code in VB.Net I get the following compile error:

"Extension method 'Add' has some type constraints that can never be satisfied".

I find this really puzzling as the same type constraints can be satisfied in C#.

So my question is this: Why does this not work in VB? Is there a way to make these same type constraints work in VB? Have I made a mistake converting the code? I hope somebody can shed some light on this as I have been scratching my head on this one for a while. :)

(Incase you are curious the extension method is intended to make it simple to add multiple values into a dictionary under a single key (such as multiple orders under one customer). But this is unimportant, I am solely concerned about the puzzling behaviour I am observing in VB).

Here is the C# Version that works:

/// <summary>
/// Adds the specified value to the multi value dictionary.
/// </summary>
/// <param name="key">The key of the element to add.</param>
/// <param name="value">The value of the element to add. The value can be null for reference types.</param>
public static void Add<KeyType, ListType, ValueType>(this Dictionary<KeyType, ListType> thisDictionary, 
                                                     KeyType key, ValueType value)
where ListType : IList<ValueType>, new()
{
    //if the dictionary doesn't contain the key, make a new list under the key
    if (!thisDictionary.ContainsKey(key))
    {
        thisDictionary.Add(key, new ListType());
    }

    //add the value to the list at the key index
    thisDictionary[key].Add(value);
}

Here is the VB version that doesn't compile:

''' <summary> 
''' Adds the specified value to the multi value dictionary. 
''' </summary> 
''' <param name="key">The key of the element to add.</param> 
''' <param name="value">The value of the element to add. The value can be null for reference types.</param> 
<System.Runtime.CompilerServices.Extension()> _
Public Sub Add(Of KeyType, ListType As {IList(Of ValueType), New}, ValueType) _
              (ByVal thisDictionary As Dictionary(Of KeyType, ListType), ByVal key As KeyType, ByVal value As ValueType)
    'if the dictionary doesn't contain the key, make a new list under the key 
    If Not thisDictionary.ContainsKey(key) Then
        thisDictionary.Add(key, New ListType())
    End If

    'add the value to the list at the key index 
    thisDictionary(key).Add(value)
End Sub
like image 579
Doctor Jones Avatar asked Dec 04 '08 15:12

Doctor Jones


2 Answers

The problem only happens when <System.Runtime.CompilerServices.Extension()> is present. The VB compiler imposes a restriction that the constraints must be verifiable with the first argument alone. Since the first argument for the extension method (Dictionary(Of KeyType, ListType)) is dependant upon the third argument (ValueType) via the IList(Of TValue) constraint, this cannot be compiled in VB.

like image 119
configurator Avatar answered Sep 20 '22 12:09

configurator


The reason is explained here: http://msdn.microsoft.com/en-us/library/bb385206.aspx

The VB compiler might be a little pickier in this case because it has to support optional parameters. There are no optional parameters in C# (yet).

like image 37
Dirk Vollmar Avatar answered Sep 21 '22 12:09

Dirk Vollmar