C# 使用表达式/lambda比较/筛选两个列表的通用方法

C# 使用表达式/lambda比较/筛选两个列表的通用方法,c#,.net,linq,generic-list,C#,.net,Linq,Generic List,我想比较两个列表,基于过滤器表达式;不确定如何为泛型方法构造lambda表达式;请参考下面的代码;或者有没有一种更简单的方式通过LINQ的交叉点 namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Data d1 = new Data {Id = 1, Name = "One"}; Data

我想比较两个列表,基于过滤器表达式;不确定如何为泛型方法构造lambda表达式;请参考下面的代码;或者有没有一种更简单的方式通过LINQ的交叉点

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Data d1 = new Data {Id = 1, Name = "One"};
            Data d2 = new Data { Id = 2, Name = "Two" };
            Data d3 = new Data { Id = 3, Name = "Three" };

            Data d4 = new Data { Id = 1, Name = "One" };
            Data d5 = new Data { Id = 2, Name = "Two" };
            Data d6 = new Data { Id = 4, Name = "Four" };

            List<Data> original = new List<Data> {d1, d2, d3};
            List<Data> filterItems = new List<Data> {d4, d5, d6};

            List<Data> result = original.FilterDataList(filterItems);

            //How to call this method?
            List<Data> genericCall = original.FilterList<Data>(filterItems, data => data.Id ?????????????)
        }
    }

    public class Data
    {
        public long Id;
        public string Name;
    }

    public static class Extensions
    {
        public static List<Data> FilterDataList(this List<Data> sourceList, List<Data> filterOutItems)
        {
            return sourceList.Where(p => filterOutItems.All(l => l.Id != p.Id)).ToList();
        }

        public static List<T> FilterList<T>(this List<T> sourceList, List<T> filterOutItems, Func<T, bool> filterExpression)
        {
            return sourceList.Where(p => filterOutItems.All(filterExpression)).ToList();
        }
    }
}
命名空间控制台应用程序1
{
班级计划
{
静态void Main(字符串[]参数)
{
数据d1=新数据{Id=1,Name=“One”};
数据d2=新数据{Id=2,Name=“Two”};
数据d3=新数据{Id=3,Name=“Three”};
数据d4=新数据{Id=1,Name=“One”};
数据d5=新数据{Id=2,Name=“Two”};
数据d6=新数据{Id=4,Name=“Four”};
原始列表=新列表{d1,d2,d3};
List filterItems=新列表{d4,d5,d6};
列表结果=原始的.FilterDataList(filterItems);
//如何调用此方法?
List genericCall=original.FilterList(filterItems,data=>data.Id????)
}
}
公共类数据
{
公共长Id;
公共字符串名称;
}
公共静态类扩展
{
公共静态列表筛选器目录(此列表源列表、列表筛选器使用项)
{
返回sourceList.Where(p=>filterOutItems.All(l=>l.Id!=p.Id)).ToList();
}
公共静态列表筛选器列表(此列表源列表、列表筛选器使用项、函数筛选器表达式)
{
返回sourceList.Where(p=>filterOutItems.All(filtereexpression)).ToList();
}
}
}

您想要的输出是什么?你试过第一个结果了吗?似乎您应该仔细阅读可枚举文档-您正在使用的。所有您最可能指的都是。任何,一般来说,它会让您更好地了解使用LINQ可能实现的功能。

您希望的输出是什么?你试过第一个结果了吗?似乎您应该仔细阅读可枚举文档-您正在使用的。所有您最可能指的都是。任何,一般来说,它会让您更好地了解LINQ的可行性。

我不清楚您想做什么。您的
FilterDataList
似乎与
.ToList()
相同。
过滤器列表中的
.Where
未使用
p
(lambda的参数),因此我不清楚您想对过滤器表达式执行什么操作。可能您正在寻找一个不同的
IEqualityComparer
一起使用,除了()
,您必须将其定义为一个单独的类。

我不清楚您想做什么。您的
FilterDataList
似乎与
.ToList()
相同。
过滤器列表中的
.Where
未使用
p
(lambda的参数),因此我不清楚您想对过滤器表达式执行什么操作。可能您正在寻找一个不同的
IEqualityComparer
Except()
一起使用,您必须将其定义为一个单独的类。

如果我正确理解您的问题,
FilterList
FilterDataList
的通用版本,其中您将lambda作为参数传递。在这种情况下,您将按如下方式调用该方法:

List<Data> genericCall = original.FilterList<Data>(filterItems, (x, y) => x.Id != y.Id);
original.Except<Data>(filterItems, (x, y) => x.Id != y.Id);
List genericall=original.FilterList(filteriems,(x,y)=>x.Id!=y.Id);
如果您想使用@ivancho和@perelman建议的方法,可以使用以下方法:

public static class EnumerableExtension
{
    public static IEnumerable<T> Except<T>(this IEnumerable<T> listA, IEnumerable<T> listB,
                                           Func<T, T, bool> lambda)
    {
        return listA.Except(listB, new Comparer<T>(lambda));
    }

    public static IEnumerable<T> Intersect<T>(this IEnumerable<T> listA, IEnumerable<T> listB,
                                              Func<T, T, bool> lambda)
    {
        return listA.Intersect(listB, new Comparer<T>(lambda));
    }
}
公共静态类EnumerableExtension
{
公共静态IEnumerable除外(此IEnumerable列表A、IEnumerable列表B、,
Func lambda)
{
返回listA.Except(listB,新比较器(lambda));
}
公共静态IEnumerable Intersect(此IEnumerable listA、IEnumerable listB、,
Func lambda)
{
返回listA.Intersect(listB,新比较器(lambda));
}
}
你可以这样称呼它:

List<Data> genericCall = original.FilterList<Data>(filterItems, (x, y) => x.Id != y.Id);
original.Except<Data>(filterItems, (x, y) => x.Id != y.Id);
original.Except(filteriems,(x,y)=>x.Id!=y.Id);

如果我正确理解了您的问题,
FilterList
FilterDataList
的通用版本,其中您将lambda作为参数传递。在这种情况下,您将按如下方式调用该方法:

List<Data> genericCall = original.FilterList<Data>(filterItems, (x, y) => x.Id != y.Id);
original.Except<Data>(filterItems, (x, y) => x.Id != y.Id);
List genericall=original.FilterList(filteriems,(x,y)=>x.Id!=y.Id);
如果您想使用@ivancho和@perelman建议的方法,可以使用以下方法:

public static class EnumerableExtension
{
    public static IEnumerable<T> Except<T>(this IEnumerable<T> listA, IEnumerable<T> listB,
                                           Func<T, T, bool> lambda)
    {
        return listA.Except(listB, new Comparer<T>(lambda));
    }

    public static IEnumerable<T> Intersect<T>(this IEnumerable<T> listA, IEnumerable<T> listB,
                                              Func<T, T, bool> lambda)
    {
        return listA.Intersect(listB, new Comparer<T>(lambda));
    }
}
公共静态类EnumerableExtension
{
公共静态IEnumerable除外(此IEnumerable列表A、IEnumerable列表B、,
Func lambda)
{
返回listA.Except(listB,新比较器(lambda));
}
公共静态IEnumerable Intersect(此IEnumerable listA、IEnumerable listB、,
Func lambda)
{
返回listA.Intersect(listB,新比较器(lambda));
}
}
你可以这样称呼它:

List<Data> genericCall = original.FilterList<Data>(filterItems, (x, y) => x.Id != y.Id);
original.Except<Data>(filterItems, (x, y) => x.Id != y.Id);
original.Except(filteriems,(x,y)=>x.Id!=y.Id);

感谢所有人指出LINQ(扩展除外),这是我的最终解决方案

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Data d1 = new Data {Id = 1, Name = "One"};
            Data d2 = new Data { Id = 2, Name = "Two" };
            Data d3 = new Data { Id = 3, Name = "Three" };

            Data d4 = new Data { Id = 1, Name = "One" };
            Data d5 = new Data { Id = 2, Name = "Two" };


            List<Data> original = new List<Data> {d1, d2, d3};
            List<Data> filterItems = new List<Data> {d4, d5, d6};


            List<Data> datas = original.Except(filterItems, (x, y) => x.Id == y.Id).ToList();
        }
    }

    public class Data
    {
        public long Id;
        public string Name;
    }

    public static class EnumerableExtension
    {
        public static IEnumerable<T> Except<T>(this IEnumerable<T> listA, IEnumerable<T> listB,
                                               Func<T, T, bool> lambda)
        {
            return listA.Except(listB, new Comparer<T>(lambda));
        }

        public static IEnumerable<T> Intersect<T>(this IEnumerable<T> listA, IEnumerable<T> listB,
                                                  Func<T, T, bool> lambda)
        {
            return listA.Intersect(listB, new Comparer<T>(lambda));
        }
    }


    public class Comparer<T> : IEqualityComparer<T>
    {
        private readonly Func<T, T, bool> _expression;

        public Comparer(Func<T, T, bool> lambda)
        {
            _expression = lambda;
        }

        public bool Equals(T x, T y)
        {
            return _expression(x, y);
        }

        public int GetHashCode(T obj)
        {
            /*
             If you just return 0 for the hash the Equals comparer will kick in. 
             The underlying evaluation checks the hash and then short circuits the evaluation if it is false.
             Otherwise, it checks the Equals. If you force the hash to be true (by assuming 0 for both objects), 
             you will always fall through to the Equals check which is what we are always going for.
            */
            return 0;
        }
    }


}
命名空间控制台应用程序1
{
班级计划
{
静态void Main(字符串[]参数)
{
数据d1=新数据{Id=1,Name=“One”};
数据d2=新数据{Id=2,Name=“Two”};
数据d3=新数据{Id=3,Name=“Three”};
数据d4=新数据{Id=1,Name=“One”};
数据d5=新数据{Id=2,Name=“Two”};
原始列表=新列表{d1,d2,d3};
List filterItems=新列表{d4,d5,d6};
列表数据=original.Except(filteriems,(x,y)=>x.Id==y.Id).ToList();
}
}
公共类数据
{
公共长Id;
公共字符串名称;
}
公共静态类EnumerableExtension
{
公共静态IEnumerable(此IEnu除外