不同的工作不使用LINQ到对象 [英] Distinct not working with LINQ to Objects

查看:143
本文介绍了不同的工作不使用LINQ到对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 类节目
{
    静态无效的主要(字串[] args)
    {
        名单<图书>书=新的名单,其中,图书>
        {
            新书
            {
                NAME =C#中的深度,
                作者=新的名单,其中,作者和GT;
                {
                    新的作者
                    {
                        名字=乔恩,名字=飞碟
                    },
                     新的作者
                    {
                        名字=乔恩,名字=飞碟
                    },
                }
            },
            新书
            {
                NAME =LINQ在行动,
                作者=新的名单,其中,作者和GT;
                {
                    新的作者
                    {
                        名字=法布里斯,名字=Marguerie
                    },
                     新的作者
                    {
                        名字=史蒂夫,名字=Eichert
                    },
                     新的作者
                    {
                        名字=吉姆,姓氏=伍利
                    },
                }
            },
        };


        变种临时= books.SelectMany(书=> book.Authors).Distinct();
        的foreach(在临时变种的作者)
        {
            Console.WriteLine(author.FirstName ++ author.LastName);
        }

        Console.Read();
    }

}
公共类图书
{
    公共字符串名称{;组; }
    公开名单<作者>作者{获得;组; }
}
公共类作者
{
    公共字符串名字{获得;组; }
    公共字符串名字{获得;组; }
    公众覆盖布尔等于(obj对象)
    {
        返回true;
        //如果(!obj.GetType()= typeof运算(作者))返回false;
        //否则返回((作者)OBJ).FirstName == this.FirstName和放大器;&安培; ((作者)OBJ).FirstName == this.LastName;
    }

}
 

这是基于LINQ在行动的范例。清单4.16。

这将打印乔恩斯基特两次。为什么?我甚至试过作者类中重写Euals方法。尽管如此鲜明似乎并没有工作。我在想什么?

编辑: 我增加了==和!=运算符重载了。仍然没有帮助。

 公共静态布尔运算符==(作者一,作者B)
    {
        返回true;
    }
    公共静态布尔运算符!=(作者一,作者B)
    {
        返回false;
    }
 

解决方案

LINQ分明是不是当涉及到​​自定义对象的智能。

它所做的就是看看你的名单,并看到它有两个不同的对象(它并不关心,他们对成员字段的值相同)。

一个解决方法是实施IEquatable接口,如图这里

如果您修改Author类,像这样它应该工作。

 公共类作者:IEquatable<作者>
{
    公共字符串名字{获得;组; }
    公共字符串名字{获得;组; }

    公共布尔等于(作者等)
    {
        如果(名字== other.FirstName和放大器;&安培;姓氏== other.LastName)
            返回true;

        返回false;
    }

    公众覆盖INT GetHash code()
    {
        INT hashFirstName =姓== NULL? 0:FirstName.GetHash code();
        INT hashLastName =名字== NULL? 0:LastName.GetHash code();

        返回hashFirstName ^ hashLastName;
    }
}
 

 class Program
{
    static void Main(string[] args)
    {
        List<Book> books = new List<Book> 
        {
            new Book
            {
                Name="C# in depth",
                Authors = new List<Author>
                {
                    new Author 
                    {
                        FirstName = "Jon", LastName="Skeet"
                    },
                     new Author 
                    {
                        FirstName = "Jon", LastName="Skeet"
                    },                       
                }
            },
            new Book
            {
                Name="LINQ in Action",
                Authors = new List<Author>
                {
                    new Author 
                    {
                        FirstName = "Fabrice", LastName="Marguerie"
                    },
                     new Author 
                    {
                        FirstName = "Steve", LastName="Eichert"
                    },
                     new Author 
                    {
                        FirstName = "Jim", LastName="Wooley"
                    },
                }
            },
        };


        var temp = books.SelectMany(book => book.Authors).Distinct();
        foreach (var author in temp)
        {
            Console.WriteLine(author.FirstName + " " + author.LastName);
        }

        Console.Read();
    }

}
public class Book
{
    public string Name { get; set; }
    public List<Author> Authors { get; set; }
}
public class Author
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public override bool Equals(object obj)
    {
        return true;
        //if (obj.GetType() != typeof(Author)) return false;
        //else return ((Author)obj).FirstName == this.FirstName && ((Author)obj).FirstName == this.LastName;
    }

}

This is based on an example in LINQ in action. Listing 4.16.

This prints Jon Skeet twice. Why? I have even tried overriding Euals method in Author class. Still Distinct does not seem to work. What am I missing?

Edit: I have added == and != operator overload too. Still no help.

 public static bool operator ==(Author a, Author b)
    {
        return true;
    }
    public static bool operator !=(Author a, Author b)
    {
        return false;
    }

解决方案

LINQ Distinct is not that smart when it comes to custom objects.

All it does is look at your list and see that it has two different objects (it doesn't care that they have the same values for the member fields).

One workaround is to implement the IEquatable interface as shown here.

If you modify your Author class like so it should work.

public class Author : IEquatable<Author>
{
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public bool Equals(Author other)
    {
        if (FirstName == other.FirstName && LastName == other.LastName)
            return true;

        return false;
    }

    public override int GetHashCode()
    {
        int hashFirstName = FirstName == null ? 0 : FirstName.GetHashCode();
        int hashLastName = LastName == null ? 0 : LastName.GetHashCode();

        return hashFirstName ^ hashLastName;
    }
}

这篇关于不同的工作不使用LINQ到对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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