views:

61

answers:

3

Here is an exemple of the situation:

public class ScheduleArea : IArea<Schedule>
{
//....
private Dictionary<int, ScheduleArea> subArea;
//.... 

#region IArea<Schedule> Members

public ICollection<KeyValuePair<int, IArea<Schedule>>> SubArea
{
     get {
        return (Collection<KeyValuePair<int, IArea<Schedule>>>)this.subArea;//Error here
     }

}

#endregion

subArea is containing a ScheduleArea that is in fact an IArea. Why does the conversion doesnt work and how can I fix it?

+1  A: 

You're running into the very popular problem of generic co/contra-variance. You're basically trying to cast a Dictionary<int, ScheduleArea> to a Dictionary<int, IArea<Schedule>>. Generics in .NET aren't assignable like that

However, you could cast it to an IDictionary<int, ScheduleArea> or ICollection<KeyValuePair<int, ScheduleArea>>. To actually get an ICollection<KeyValuePair<int, IArea<Schedule>> you need to either change the subArea variable type or create a new dictionary:

Dictionary<int, IArea<Schedule>> dict = new Dictionary<int, IArea<Schedule>>(subArea.Count);

foreach (KeyValuePair<int, ScheduleArea> kvp in subArea) 
{
    dict.Add(kvp.Key, kvp.Value);
}

return dict;

Also, Dictionary doesn't inherit off Collection - you need to use ICollection instead

thecoop
C# 2 - no var available. I'd also suggest that if there's no need for hashing any more, I'd just go with List instead of a Dictionary for the new collection.
Jon Skeet
Ah, no var. Edited...
thecoop
A: 

It doesn't work because you're assuming generic variance, which doesn't work at all until .NET 4.0.

The simplest way forward is going to be to do it manually (given the "c#2.0" tag I assume you can't use LINQ):

List<KeyValuePair<int, IArea<Schedule>>> list = new
    List<KeyValuePair<int, IArea<Schedule>>>(subArea.Count);
foreach (KeyValuePair<int, ScheduleArea> pair in subArea)
{
    list.Add(new KeyValuePair<int, IArea<Schedule>>(pair.Key, pair.Value);
}
return list;

I would make this a method rather than a property though, given the amount of copying going on.

Jon Skeet
Jon: A small nitpick: `Dictionary<K,V>` does implement `ICollection<KeyValuePair<K,V>>`.
LukeH
http://bit.ly/6NMnTV here is the proof that Dictionary<K,V> does implement ICollection<KeyValuePair<K,V>>
Daok
but not `Collection<KeyValuePair<K,V>>`
thecoop
Oops :( Editing...
Jon Skeet
A: 

Ah, the daily question about covariance.

See: http://stackoverflow.com/questions/1834229/why-cant-i-pass-listcustomer-as-a-parameter-to-a-method-that-accepts-listobje

and

http://stackoverflow.com/questions/1817300/how-to-convert-list-of-derived-class-objects-to-list-of-base-class-objects

To sum up: each item will have to be converted into a new KeyValuePair for the new collection.

Jesse C. Slicer