Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lambdas over polymorphic classes

Tags:

c#

lambda

linq

In the code below, note that Bar derives from Foo.

class Program
{
    public class Foo
    {
        public string data { get; set; }
    }

    public class Bar : Foo
    {
    }

    static void Main(string[] args)
    {
        var bars = new List<Bar>();

        bars.Add(new Bar() { data = "hello" });
        bars.Add(new Bar() { data = "world" });

        var resultsA = GetFoos(bars, (b => b.data.StartsWith("h")));
        var resultsB = GetBars(bars, (b => b.data.StartsWith("h")));
    }

    static List<Foo> GetFoos(List<Foo> fooList, Func<Foo, bool> criteria)
    {
        return fooList.Where(criteria).ToList();
    }

    static List<Bar> GetBars(List<Bar> barList, Func<Bar, bool> criteria)
    {
        return barList.Where(criteria).ToList();
    }
}

The GetFoos method call results in this compiler error message: Argument 1: cannot convert from 'System.Collections.Generic.List<Program.Bar>' to 'System.Collections.Generic.List<Program.Foo>'

However, when that line is commented out, the call to GetBars() executes correctly.

Is what I'm trying to accomplish here, a query against a common ancestor class, possible with linq?

like image 826
overslacked Avatar asked May 01 '26 05:05

overslacked


1 Answers

Only interfaces can be covariant. Since you are trying to assign a List<Derived> to a List<Base>, you need to use a covariant interface instead. IEnumerable is already covariant, so just change your code to:

static List<Foo> GetFoos(IEnumerable<Foo> fooList, Func<Foo, bool> criteria)
{
    return fooList.Where(criteria).ToList();
}

static List<Bar> GetBars(IEnumerable<Bar> barList, Func<Bar, bool> criteria)
{
    return barList.Where(criteria).ToList();
}

Proof on IdeOne

like image 189
BradleyDotNET Avatar answered May 02 '26 23:05

BradleyDotNET