views:

63

answers:

2

I have created a Dictionary class (MyDictionary for the example). I am currently trying to pass MyDictionary into a function, filter it into a new instance of MyDictionary and pass this new instance into another method.

When I am attempting to create the second instance from the filtered first instance of MyDictionary via Lambda Expressions and the ToDictionary Method, I am getting the following error:

Unable to cast object of type 'System.Collections.Generic.Dictionary`2[System.Int32,System.String]' to type 'MyDictionary'.

I have simplified the example and recreated it in LINQPad and am getting the same error.

Here's the simplified version of my code:

Sub Main
 Dim di1 As New MyDictionary
 di1(1) = "One"
 di1(2) = "Two"
 di1(3) = "Three"
 di1(4) = "Four"
 Dim di2 As MyDictionary= _
  CType(di1.Where(Function(w) w.Value.Contains("T")) _
   .ToDictionary(Function(tdk) tdk.Key, Function(tdv) tdv.Value), MyDictionary)
End Sub

Public Class MyDictionary
 Inherits Dictionary(Of Integer, String)
 Public Sub New()
  MyBase.New()
 End Sub
 Public Sub New(ByVal dictionary As IDictionary(Of Integer, String))
  MyBase.New(dictionary)
 End Sub
End Class

Thanks in advance, -Aaron


Per Brennen's Post: I am able to do the following and it's fine, I was just hoping to not do it this way.

 Sub Main
     Dim di1 As New MyDictionary
     di1(1) = "One"
     di1(2) = "Two"
     di1(3) = "Three"
     di1(4) = "Four"
     Dim di2 = _
      di1.Where(Function(w) w.Value.Contains("T")) _
       .ToDictionary(Function(tdk) tdk.Key, Function(tdv) tdv.Value)
     Dim di3 As New MyDictionary(di2)
 End Sub

Public Class MyDictionary
 Inherits Dictionary(Of Integer, String)
 Public Sub New()
  MyBase.New()
 End Sub
 Public Sub New(ByVal dictionary As IDictionary(Of Integer, String))
  MyBase.New(dictionary)
 End Sub
End Class

Does anyone else have any thoughts on how I could skip the third MyDictionary instance?

A: 

What's being returned from ToDictionary is a Dictionary, not a MyDictionary. MyDictionary is a Dictionary, but not the other way around, so it doesn't make sense to cast from Dictionary to MyDictionary.

In other words, less-derived types can't automagically be converted to more-derived types.

Brennan Vincent
Thanks Brennen for the quick response. Please see my updated question.
Airn5475
A: 

As Brennan mentions, MyDictionary and Dictionary(Of Integer, String) are completely different types, even though one derives from the other.

The ToDictionary call returns a Dictionary(Of Integer, String) and you're then trying to cast that dictionary to a MyDictionary.

You could create your own ToMyDictionary extension method to workaround this:

Dim di2 As MyDictionary = _
    di1.Where(Function(w) w.Value.Contains("T")) _
       .ToMyDictionary(Function(tdk) tdk.Key, Function(tdv) tdv.Value)

' ...

<Extension()>
Public Shared Function ToMyDictionary(Of T)( _
    ByVal source As IEnumerable(Of T), _
    ByVal keySelector As Func(Of T, Integer), _
    ByVal valueSelector As Func(Of T, String)) As MyDictionary

    Dim result As New MyDictionary
    Dim item As T

    For Each item In source
        result.Add(keySelector.Invoke(item), valueSelector.Invoke(item))
    Next

    Return result
End Function

(Apologies if the syntax isn't entirely correct: my VB is very rusty these days.)

LukeH
Thanks LukeH for the suggestion. As much as I love extension methods, I will probably pass on them this time. It would be a slight overkill at this point.
Airn5475