.NET 6 IntersectBy 和 exceptBy 示例

web*_*442 19 .net c# linq .net-6.0

有人可以为我提供一个有关如何使用 .NET 6 LINQIntersectByExceptBy方法的小示例吗?MSDN 没有任何示例,我尝试的示例由于 CS0411 错误而无法编译。我尝试过的例子:

namespace Test
{
    internal struct Example
    {
        public int X { get; set; }
        public int Y { get; set; }

        public override string ToString()
        {
            return $"{X}, {Y}";
        }
    }

    public class Program
    {
        public static void Main()
        {
            var elements = new List<Example>
            {
                new Example { X = 10, Y = 20 },
                new Example { X = 11, Y = 23 },
            };

            var elements2 = new List<Example>
            {
                new Example { X = 10, Y = 12 },
                new Example { X = 44, Y = 20 },
            };


            //ok
            var union = elements.UnionBy(elements2, x => x.X);
            
            //CS0411 - Why ?
            var intersect = elements.IntersectBy(elements2, x => x.X);

            //CS0411 - Why ?
            var except = elements.ExceptBy(elements2, x => x.X);

            Console.ReadKey();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Has*_*niH 25

尽管文档没有任何示例,但它指出选择器函数应该选择TKey第二个集合的类型。以下应该有效:

var intersect = elements.IntersectBy(elements2, x => x);
var except = elements.ExceptBy(elements2, x => x);
Run Code Online (Sandbox Code Playgroud)

虽然我认为这可能更接近你想要的:

var intersect = elements.IntersectBy(elements2.Select(e => e.X), x => x.X);
Run Code Online (Sandbox Code Playgroud)

对于更复杂的类型,您可能需要考虑实现 IEqualityComparer 并使用以 1 作为参数的重载。

  • 我想知道为什么他们选择使用不同的模式“UnionBy”、“IntersectBy”和“ExceptBy”。 (3认同)
  • @BradleyUffner 答案是 IMO,因为 `UnionBy` 需要返回单个连接结果列表,因此它们需要是相同的类型。而 `IntersectBy` 和 `ExceptBy` 只返回源集合中的结果,因此使用这些参数,您可以使用 `IEnumerable&lt;TKey&gt;`,如果您需要从不同的集合中进行选择,只需使用 `Select` (这不会)对于“UnionBy”来说确实有意义) (3认同)

Mic*_*ael 5

我自己做了ExceptByProperty这样的方法

用法:

var new = items.ExceptByProperty(duplicateItems, x => x.Id).ToList();
Run Code Online (Sandbox Code Playgroud)

代码:

public static class EnumerableExtensions
{
    public static IEnumerable<TSource> ExceptByProperty<TSource, TProperty>(this IEnumerable<TSource> first, IEnumerable<TSource> second, Func<TSource, TProperty> keySelector)
    {
        return first.ExceptBy(second, x => x, GenericComparer<TSource, TProperty>.Comparer(keySelector));
    }

}

public sealed class GenericComparer<T, TProperty> : IEqualityComparer<T>
{
    public static IEqualityComparer<T> Comparer(Func<T, TProperty> selector)
    {
        return new GenericComparer<T, TProperty>(selector);
    }

    private readonly Func<T, TProperty> selector;

    public GenericComparer(Func<T, TProperty> selector)
    {
        this.selector = selector;
    }

    public bool Equals(T? x, T? y)
    {
        if (x == null || y == null) return false;

        return Equals(selector(x), selector(y));
    }

    public int GetHashCode([DisallowNull] T obj)
    {
        object? value = selector(obj);

        if (value == null) return obj.GetHashCode();

        return value.GetHashCode();
    }
}
Run Code Online (Sandbox Code Playgroud)