簡體   English   中英

如何在lambda表達式中為匿名變量編寫IEqualityComparer?

[英]How to write IEqualityComparer for anonymous variables in lambda expression?

我想知道有一種方法可以在lambda表達式中為匿名變量實現IEqualityComparer,或者,無論如何,我需要編寫類來將匿名變量轉換為sprecific類並創建一個我需要實現IEqualtyComparer的類?

我編寫了創建笛卡爾(Decart)生產的代碼:我定義了類Decart。

public class Decart
{
    public int X;
    public int Y;
}

我為Decart類定義了IEqualtityComparer

public class Ext : IEqualityComparer<Decart>
{

    public bool Equals(Decart x, Decart y)
    {
        if ((x.X == y.X && x.Y == y.Y) ||
            x.X == y.Y && x.Y == y.X)
            return true;

        return false;
    }

    public int GetHashCode(Decart obj)
    {
        return obj.X + obj.Y;
    }
}

我運行這段代碼:

static void Main(string[] args)
{
    Ext ext = new Ext();
    IEnumerable<int> input = Enumerable.Range(1, 3);
        var secondResult = input
        .SelectMany(x => input.Select(y => new Decart{ X = x, Y = y }))
        .Distinct(new Ext());
    Console.WriteLine(new string('-', 50));

    foreach (var x in secondResult)
    {
        Console.WriteLine(string.Format("{0} {1}", x.X, x.Y));
    }
    //output:
    //1 1
    //1 2
    //1 3
    //2 2
    //2 3
    //3 3
}

我想運行下一個代碼而不為匿名變量定義一個類,一個用於實現IEqualityComparer的類。

    var thirdResult = input
        .SelectMany(x => input
            .SelectMany(y => input
                .Select(z => new { x, y, z })))
                    .Distinct( ???? );

//in this case output need to be like this:
//1 1 1
//1 2 1
//1 3 1
//2 1 2
//2 2 2
//2 3 2
//3 1 3
//3 2 3
//3 3 3

怎么做 ?

您可以聲明IEqualityComparer<T>實現,該實現將委托作為GetHashCodeEquals接口方法的實現。 然后你可以傳入匿名方法作為實現。

public static IEqualityComparer<T> CreateEqualityComparer<T>(T ignore, Func<T, int> getHashCode, Func<T, T, bool> equals) => new DelegatedEqualityComparer<T>(getHashCode, equals);

public class DelegatedEqualityComparer<T> : EqualityComparer<T> {
    private Func<T, int> getHashCode;
    private Func<T, T, bool> equals;
    public DelegatedEqualityComparer(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));
        this.getHashCode=getHashCode;
        this.equals=equals;
    }
    public override int GetHashCode(T x) => getHashCode(x);
    public override bool Equals(T x, T y) => equals(x, y);
}

你這樣使用它:

var equalityComparer = CreateEqualityComparer(true ? null : new { x = 0, y = 0 }, a => a.x+a.y, (a, b) => (a.x==b.x&&a.y==b.y)||(a.x==b.y&&a.y==b.x));
var result = input
    .SelectMany(x => input
        .Select(y => new { x, y }))
    .Distinct(equalityComparer);

true ? null : new { x = 0, y = 0 }含義true ? null : new { x = 0, y = 0 } true ? null : new { x = 0, y = 0 }

需要CreateEqualityComparer( T ignore )的第一個參數,以允許編譯器推斷類型T ,因為您不能拼寫匿名類型的名稱。 三元運算符的true條件使編譯器始終選擇左分支null ,但由於三元運算符的兩個分支必須返回相同的類型,因此new { x = 0, y = 0 }使編譯器隱式地將null為給定的匿名類型。

另外,規范中的相關說明:

7.6.10.6匿名對象創建表達式
在同一程序中,兩個匿名對象初始值設定項以相同的順序指定相同名稱和編譯時類型的屬性序列,這將生成相同匿名類型的實例。

目前還不清楚你在問什么。

我假設你想要像這樣對這個類的維度進行整合

public class Decart
{
    public int[] dim;
}

然后你可以擴展比較器

public class Ext : IEqualityComparer<Decart>
{

    public bool Equals(Decart x, Decart y)
    {
        for(int i=0; i< x.dim.Length;i++) 
        if (x.dim[i] != y.dim[i] ) 
            return false; 
        return true;
    }

    public int GetHashCode(Decart obj)
    {
        return obj.dim.Sum();
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM