3

This may be rather obvious but I can't seem to get it. For a rather convoluted refactoring (a.k.a hack) I need to be able to swap out the 'type' of list based on some flags. To make the swap easier and prevent "downstream" changes of nested functions I decided to do something like this:

List<Object> myList = new List<Tuple<string, bool>>();

Based on certain flags I'd like to do this instead:

List<Object> myList= new List<MyObject>();

That way I can use myList almost as is without too many changes in the methods that consume the list. In most cases they only add elements to the list and not read from it so this 'hack' would be rather convenient.

However, I can't really seem to do this as the C# compiler complains that it cannot cast from System.Tuple to Object. What really am I missing?

PhD
  • 11,202
  • 14
  • 64
  • 112

2 Answers2

4

List<T> is not a covariant type.

If it were, one problem is that classes may operate differently depending upon their assigned generic type. For example, imagine this:

class Foo<T>
{
    public bool FooBar()
    {
        return typeof(T).Name.ToLower() == "object";
    }
}

Now, if you allowed Foo<string> to be cast to Foo<object>, what does FooBar() return after the cast?

There are three solutions:

  1. Just use List<object> and add Tuple<string, bool> type instances to it.
  2. Cast to IList. This has potential downsides, though, as you're expecting a List<T> and a different class that implements IList might be passed.
  3. Turn your accepted list types into a hierarchy and use a list of the base type, for example:

.

abstract class Animal { }

class Cat : Animal { }
class Dog : Animal { }

public List<Animal> animals = new List<Animal>();

Then you can call .Add() and other methods with Cat or Dog objects as parameters, check the types of each entry with is, and avoid the cast entirely. Whether this is appropriate depends on your types and how they interact, though.

Polynomial
  • 27,674
  • 12
  • 80
  • 107
1

List<T> isn't covariant. You can't do that. If you want, create a List<object> and fill that with all elements. Although I don't really see the advantage of using a strongly typed generic list with object.

Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321