8

does anyone know if it is possible to cast a generic type with a certain type parameter (e.g. Bar) to the same generic type with the type parameter being a base type of Bar (such as object in my case). And, if it is possible, how would it be done?

What I want to do is have a collection of Foo<object> but be able to add Foos with more specific type arguments.

Thanks

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
Michael
  • 81
  • 2
  • 2
    For future reference, this is called covariance. C# 4 has this feature for interfaces and delegates. – R. Martinho Fernandes Apr 07 '10 at 17:00
  • see http://stackoverflow.com/questions/245607/ – Cheeso Apr 07 '10 at 17:02
  • What he wants ("a collection of Foo but be able to add Foos with more specific type arguments") doesn't require C# 4 covariance - it works currently, and has since .NET 2. – Reed Copsey Apr 07 '10 at 17:04
  • @Reed: It looks like Michael wants to add `Foo` to `Collection>`. This requires covariance from C# 4. – Roman Boiko Apr 07 '10 at 17:09
  • 1
    @Roman: Hrm... If that's the case, it'd require covariance. Not clear, since there's no code shown. That wasn't how I read it originally, though. – Reed Copsey Apr 07 '10 at 17:14
  • 3
    @Reed: there was a missing single quote in the text. – Eric Lippert Apr 07 '10 at 17:53
  • Pardon my english, but by adding Foos with a "more specific type argument" I mean objects of type Foo whose type argument T is a subclass of the type argument supplied to the Collection. e.g: `IList list = new List>()` list.Add(new Foo()); list.Add(new Foo()); Please excuse me if I was being unclear. – Michael Apr 07 '10 at 22:53
  • Sorry if the above comment is unreadable - I can't edit it... – Michael Apr 07 '10 at 23:00

4 Answers4

3

You can have a collection of a base type with subclasses added. For example, the following will work:

// Using:
public class Foo {} // Base class
public class Bar : Foo {} // Subclass

// Code:
List<Foo> list = new List<Foo>();
HashSet<Foo> hash = new HashSet<Foo>();

list.Add(new Bar());
list.Add(new Foo());

hash.Add(new Bar());

Since "Bar" is a specific type of "Foo", it's perfectly legal to add it to a collection of Foo.

However, until .NET 4 and the out modifier for covariance, you cannot do:

IEnumerable<Foo> list = new List<Bar>(); // This isn't supported in .NET 3.5...
Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • 5
    Actually, you can't do that in .NET 4 either. `IList` is neither co- nor contravariant, because T shows up as both parameters (in Add) and return values (in the indexer). With `IEnumerable` it works. – R. Martinho Fernandes Apr 07 '10 at 17:08
2

Use the ConvertAll method of List(T) or Array.

http://msdn.microsoft.com/en-us/library/73fe8cwf.aspx

vfilby
  • 9,938
  • 9
  • 49
  • 62
  • 1
    He didn't really give any specifics. The ConvertAll function or List(T) or Array are exceptionally handy at these points even if you have to convert from one collection to another. – vfilby Apr 07 '10 at 17:05
2

Yes it is possible in C# 4.0!

You should look into covariance.

m0sa
  • 10,712
  • 4
  • 44
  • 91
0

Related:

How is Generic Covariance & Contra-variance Implemented in C# 4.0?

Community
  • 1
  • 1
Cheeso
  • 189,189
  • 101
  • 473
  • 713