0

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?

Patrick Desjardins
  • 136,852
  • 88
  • 292
  • 341

3 Answers3

1

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
  • 45,220
  • 19
  • 132
  • 189
  • 1
    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 Dec 04 '09 at 16:18
1

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
  • 1,421,763
  • 867
  • 9,128
  • 9,194
0

Ah, the daily question about covariance.

See: Why can't I pass List<Customer> as a parameter to a method that accepts List<object>?

and

Convert List<DerivedClass> to List<BaseClass>

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

Community
  • 1
  • 1
Jesse C. Slicer
  • 19,901
  • 3
  • 68
  • 87