传递Lambda表达式代替IComparer或IEqualityComparer或任何单方法接口? [英] Pass a lambda expression in place of IComparer or IEqualityComparer or any single-method interface?

查看:120
本文介绍了传递Lambda表达式代替IComparer或IEqualityComparer或任何单方法接口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我碰巧看到了一些代码,该家伙将lambda表达式传递给ArrayList.Sort(此处为IComparer)或IEnumerable.SequenceEqual(此处为IEnumerable列表,此处为IEqualityComparer),其中应包含IComparer或IEqualityComparer.

I happened to have seen some code where this guy passed a lambda expression to a ArrayList.Sort(IComparer here) or a IEnumerable.SequenceEqual(IEnumerable list, IEqualityComparer here) where an IComparer or an IEqualityComparer was expected.

我不确定是否看到了它,或者我只是在做梦.而且,我似乎找不到这些集合中的任何扩展,这些扩展在其方法签名中接受Func<>或委托.

I can't be sure if I saw it though, or I am just dreaming. And I can't seem to find an extension on any of these collections that accepts a Func<> or a delegate in their method signatures.

是否有这种重载/扩展方法?或者,如果不是,是否有可能像这样乱搞一遍,并通过一种算法(读取委托)来实现单方法接口?

Is there such an overload/extension method? Or, if not, is it possible to muck around like this and pass an algorithm (read delegate) where a single-method interface is expected?

更新 谢谢大家.我也这么想.我一定在做梦.我知道如何编写转换.我只是不确定我是否看过类似的东西,或者只是以为自己看过.

Update Thanks, everyone. That's what I thought. I must've been dreaming. I know how to write a conversion. I just wasn't sure if I'd seen something like that or just thought I'd seen it.

又一次更新 看,在这里,我找到了一个这样的实例.毕竟我不是在做梦.看这家伙在这里做什么.有什么作用?

Yet another update Look, here, I found one such instance. I wasn't dreaming after all. Look at what this guy is doing here. What gives?

这是另一个更新: 好的我明白了.家伙正在使用Comparison<T>重载.好的.很好,但完全容易误导您.很好,不过.谢谢.

And here's another update: Ok, I get it. The guy's using the Comparison<T> overload. Nice. Nice, but totally prone to mislead you. Nice, though. Thanks.

推荐答案

我也在Google上搜索解决方案,但没有找到令人满意的解决方案.所以我创建了一个通用的EqualityComparerFactory:

I was also googling the web for a solution, but i didn't found any satisfying one. So i've created a generic EqualityComparerFactory:

using System;
using System.Collections.Generic;

/// <summary>
/// Utility class for creating <see cref="IEqualityComparer{T}"/> instances 
/// from Lambda expressions.
/// </summary>
public static class EqualityComparerFactory
{
    /// <summary>Creates the specified <see cref="IEqualityComparer{T}" />.</summary>
    /// <typeparam name="T">The type to compare.</typeparam>
    /// <param name="getHashCode">The get hash code delegate.</param>
    /// <param name="equals">The equals delegate.</param>
    /// <returns>An instance of <see cref="IEqualityComparer{T}" />.</returns>
    public static IEqualityComparer<T> Create<T>(
        Func<T, int> getHashCode,
        Func<T, T, bool> equals)
    {
        if (getHashCode == null)
        {
            throw new ArgumentNullException(nameof(getHashCode));
        }

        if (equals == null)
        {
            throw new ArgumentNullException(nameof(equals));
        }

        return new Comparer<T>(getHashCode, equals);
    }

    private class Comparer<T> : IEqualityComparer<T>
    {
        private readonly Func<T, int> _getHashCode;
        private readonly Func<T, T, bool> _equals;

        public Comparer(Func<T, int> getHashCode, Func<T, T, bool> equals)
        {
            _getHashCode = getHashCode;
            _equals = equals;
        }

        public bool Equals(T x, T y) => _equals(x, y);

        public int GetHashCode(T obj) => _getHashCode(obj);
    }
}

想法是,CreateComparer方法采用两个参数:GetHashCode(T)的委托和Equals(T,T)的委托

The idea is, that the CreateComparer method takes two arguments: a delegate to GetHashCode(T) and a delegate to Equals(T,T)

示例:

class Person
{
    public int Id { get; set; }
    public string LastName { get; set; }
    public string FirstName { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var list1 = new List<Person>(new[]{
            new Person { Id = 1, FirstName = "Walter", LastName = "White" },
            new Person { Id = 2, FirstName = "Jesse", LastName = "Pinkman" },
            new Person { Id = 3, FirstName = "Skyler", LastName = "White" },
            new Person { Id = 4, FirstName = "Hank", LastName = "Schrader" },
        });

        var list2 = new List<Person>(new[]{
            new Person { Id = 1, FirstName = "Walter", LastName = "White" },
            new Person { Id = 4, FirstName = "Hank", LastName = "Schrader" },
        });


        // We're comparing based on the Id property
        var comparer = EqualityComparerFactory.Create<Person>(
            a => a.Id.GetHashCode(),
            (a, b) => a.Id==b.Id);
        var intersection = list1.Intersect(list2, comparer).ToList();
    }
}

这篇关于传递Lambda表达式代替IComparer或IEqualityComparer或任何单方法接口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆