views:

816

answers:

3
Public Class A

Public Class B : Inherits A

Dim DictA As Dictionary(Of Integer, A)
Dim DictB As New Dictionary(Of Integer, B)

DictA = DictB

This doesn't work, as the type can't be converted. Is this somehow possible?

A: 

This is a interesting, and quite complex aspect of Static type systems. The terms you are looking for is Covariance and Contravariance.

The c# language will get this for certain sorts of operations on Generic types in 4.0 though in a somewhat limited form.

You have it to a certain degree already in the form of

object[] x = new string[1];

Which is allowed because arrays are treated covariantly, which means that you could then do the following:

x[0] = new object();

which would throw an Exception at runtime. Do you see how the same would apply to you Dictionaries...

The c# 4.0 spec is still non final so is subject to change but for some discussions and explanations see this question

ShuggyCoUk
+4  A: 

No. You're running into the problem of generic variance, which isn't supported in .NET except in a few very particular ways.

Here's the reason: after your last line, you've got a single dictionary with two "views" onto it, effectively. Now imagine you wrote:

DictA.Add(1, New A())

(Apologies if my VB is slightly off.) That's inserted a "non-B" into the dictionary, but DictB thinks that all the values will be instances of B.

One of the main purposes of generics is to catch potential type failures at compile time rather than execution time - which means this code should fail to compile, which indeed it does precisely because of the lack of variance.

It's a bit counter-intuitive when you're used to normal inheritance, but it does make sense. A bunch of bananas isn't just a collection of fruit - it's a collection of bananas.

Java takes a somewhat different stance on this using wildcarding from the caller's side - it would let you see just the "adding" side of the dictionary for DictB, for instance, as anything you add to DictB would be fine in DictA. Java's generics are very different to .NET generics though...

Jon Skeet
A: 

Unfortunately not. This is a known absence of covariance/contravariance support. The CLR supports it, but the compilers for C# and VB.Net do not.

The next version of C# (4.0) actually does support it now, but not sure about vb.net. Also, with System.Linq, one of the extension methods is Cast() which would allow you to cast from a collection of one type to another. However it will still return IEnumerable so you need to manipulate a little bit, but I think key-value types will be harder than collections with only one generic type.

DarkwingDuck