2

I've looked around and haven't found anything quite matching my problem, though this is certainly close. Basically, I have a KeyedCollection of Page objects as a base, and I want strongly typed collections of derived objects to come from it. Specifically, I have:

public class Page public class Category : Page public class PageList<T> : KeyedCollection<string, T> where T : Page public class CategoryList : PageList<Category>

Now, this seems fine up until I want to call a method from within the PageList<T> using something like DoSomethingTo(this) which is currently declared as DoSomethingTo(PageList<Page> pageList). This gives me a casting error.

What I'd like to be able to do, as you've probably already figured out is to use DoSomething(this) from within either the PageList<T> class or within the CategoryList class.

How do I make this work...or do I? I tried similar methods to what was suggested in the question I linked above, but I couldn't get anything to work. Thanks!

Community
  • 1
  • 1

1 Answers1

1

Your problem is that PageList<Page> and PageList<Category> are not covariant. The are effectively completely unrelated types. Even though T is a derived type, the resulting generic collections are not.

If you think about it, this is correct, because otherwise there would be nothing stopping you from passing a CatagoryList to a function that expects a PageList which could then add a Page to the catagory collection which would be invalid.

To help with situations like this, C# 4 added support for covariant interfaces. These allow limited covariance by using in and out keywords to restrict what you can do.

Your linked question uses this, which you could do also.

interface IPageList<out T> where T : Page
{
}

public class PageList<T> : KeyedCollection<string, T>, IPageList<T> where T : Page
{
}


DoSomethingTo(IPageList<Page> pageList)
{   
}
GazTheDestroyer
  • 20,722
  • 9
  • 70
  • 103
  • I tried something like this, but maybe I just didn't get it right somewhere along the way. I'll poke at it again tomorrow. Thanks! –  Feb 26 '14 at 11:12
  • Ah, I remember the problem now. The problem with doing this is that IPageList is no longer a KeyedCollection, so DoSomethingTo can't iterate through it. –  Feb 26 '14 at 21:48
  • Oh, and just as importantly, I need it to be indexable as well. I'm guessing I'm asking the impossible? –  Feb 26 '14 at 22:05