Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c# Linq `List<Interface>.AddRange` Method Not Working

Tags:

c#

linq

addrange

I have an interface defined as below:

public interface TestInterface{
    int id { get; set; }
}

And two Linq-to-SQL classes implementing that interface:

public class tblTestA : TestInterface{
    public int id { get; set; }
}

public class tblTestB : TestInterface{
    public int id { get; set; }
}

I have IEnumerable lists a and b populated by the database records from tblTestA and tblTestB

IEnumerable<tblTestA> a = db.tblTestAs.AsEnumerable();
IEnumerable<tblTestB> b = db.tblTestBs.AsEnumerable();

However, the following is not permitted:

List<TestInterface> list = new List<TestInterface>();
list.AddRange(a);
list.AddRange(b);

I have to do as follows:

foreach(tblTestA item in a)
    list.Add(item)

foreach(tblTestB item in b)
    list.Add(item)

Is there something I am doing wrong? Thanks for any help

like image 869
Jimbo Avatar asked Jul 14 '10 09:07

Jimbo


1 Answers

This works in C# 4, due to generic covariance. Unlike previous versions of C#, there is a conversion from IEnumerable<tblTestA> to IEnumerable<TestInterface>.

The functionality has been in the CLR from v2, but it's only been exposed in C# 4 (and the framework types didn't take advantage of it before .NET 4 either). It only applies to generic interfaces and delegates (not classes) and only for reference types (so there's no conversion from IEnumerable<int> to IEnumerable<object> for example.) It also only works where it makes sense - IEnumerable<T> is covariant as objects only come "out" of the API, whereas IList<T> is invariant because you can add values with that API too.

Generic contravariance is also supported, working in the other direction - so for example you can convert from IComparer<object> to IComparer<string>.

If you're not using C# 4, then Tim's suggestion of using Enumerable.Cast<T> is a good one - you lose a little efficiency, but it will work.

If you want to learn more about generic variance, Eric Lippert has a long series of blog posts about it, and I gave a talk about it at NDC 2010 which you can watch on the NDC video page.

like image 85
Jon Skeet Avatar answered Sep 23 '22 02:09

Jon Skeet