views:

467

answers:

3

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
+1  A: 

I would suspect that the problem is that you used ValueType for as the name for one of the type parameters, which is an actual type in the .NET class library (System.ValueType). I can imagine that C# and VB.NET handles this differently. Try it with a different name, like TValue (and TKey just to be consistent).

csgero
I've tried changing the names of the type parameters as you suggest and it doesn't make a difference. Nice idea though.
DoctaJonez
+3  A: 

Hi,

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).

0xA3
+4  A: 

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.

configurator
It's strange that they have this restriction in VB but not in C#. This is one of the situations that highlight the fact that VB and C# have different development teams.
DoctaJonez