为什么我在执行交叉路口时没有得到结果?

时间:2015-07-18 06:47:25

标签: c# linq linq-to-sql

用户类:

public class User  
{
    public int ID { get; set; }
    public string Email { get; set; }
}

代码:

        var usersL = new List<User>()
                        {
                            new User{ID = 1,Email = "abc@foo.com"},
                            new User{ID = 2,Email = "def@foo.com"}
                        };

        var usersR = new List<User>()
                        {
                            new User{ID = 1,Email = "abc@foo.com"},
                            new User{ID = 2,Email = "def@foo.com"}
                        };

        var both = (from l in usersL select l)
            .Intersect(from users in usersR select users);

        foreach (var r in both)
            Console.WriteLine(r.Email);

返回0结果。

我知道我可以通过使用 join 来完成类似的事情,但我想使用Intersect,因为A)这最终会对某些数据库代码起作用,我们想要使用这个函数(太长时间)进入为什么)和B)我只是很好奇为什么Intersect不在这里工作。

        var both = from l in usersL
                   join r in usersR on l.ID equals r.ID
                   select l;

2 个答案:

答案 0 :(得分:1)

.Net为预定义类型提供比较逻辑。如果您的连接查询正在加入(比较)两个类型为Int(预定义类型)的ID

var both = from l in usersL
           join r in usersR on l.ID equals r.ID
           select l;

如果是交叉查询,则尝试比较两个用户定义的User类型的自定义对象。因此,您需要提供自己的自定义比较实现逻辑。

2种方式可以解决这个问题......

选项1: 实施IEqualityComparer

public class User
{
    public int ID { get; set; }
    public string Email { get; set; }
}

public class MyEqualityComparer : IEqualityComparer<User>
{
    public bool Equals(User x, User y)
    {
        if (object.ReferenceEquals(x, y))
            return true;
        if (x == null || y == null)
            return false;
        return x.ID.Equals(y.ID) &&
               x.Email.Equals(y.Email);
    }

    public int GetHashCode(User u)
    {
        return new { u.ID, u.Email }.GetHashCode();
    }
}

class Program
{
    static void Main(string[] args)
    {

        var usersL = new List<User>()
                    {
                        new User{ID = 1,Email = "abc@foo.com"},
                        new User{ID = 2,Email = "def@foo.com"}
                    };

        var usersR = new List<User>()
                    {
                        new User{ID = 1,Email = "abc@foo.com"},
                        new User{ID = 2,Email = "def@foo.com"}
                    };

        var both =  (from l in usersL select l)
          .Intersect(from users in usersR select users, new MyEqualityComparer());

        foreach (var r in both)
            Console.WriteLine(r.Email);
    }
}

选项2 覆盖自定义对象本身中的Equals和GetHashcode方法

public class User 
{
    public int ID { get; set; }
    public string Email { get; set; }

    public override bool Equals(Object obj)
    {
        // Check for null values and compare run-time types.
        if (obj == null || GetType() != obj.GetType())
            return false;

        User x = (User)obj;
        return (ID == x.ID) && (Email == x.Email);
    }

    public override int GetHashCode()
    {
        return new { ID, Email }.GetHashCode();
    }
}

class Program
{
    static void Main(string[] args)
    {

        var usersL = new List<User>()
            {
                new User{ID = 1,Email = "abc@foo.com"},
                new User{ID = 2,Email = "def@foo.com"}
            };

        var usersR = new List<User>()
            {
                new User{ID = 1,Email = "abc@foo.com"},
                new User{ID = 2,Email = "def@foo.com"}
            };

        var both = (from l in usersL select l)
          .Intersect(from users in usersR select users);

        foreach (var r in both)
            Console.WriteLine(r.Email);
    }
}

希望这有帮助。

答案 1 :(得分:0)

这是对@sundeep的回应,他说&#34;现在关注你的第二个问题......&#34; (我希望你能链接到评论) - 我只是创建一个新的答案,因为我不想破坏我原来问题的背景

实现 IEqualityComparer

的用户类
public class User : IEqualityComparer<User>
{
    public int ID { get; set; }
    public string Email { get; set; }

    public bool Equals(User x, User y)
    {
        if (object.ReferenceEquals(x, y))
            return true;
        if (x == null || y == null)
            return false;
        return x.ID.Equals(y.ID) &&
               x.Email.Equals(y.Email);
    }

    public int GetHashCode(User obj)
    {
        return new { obj.ID, obj.Email }.GetHashCode();
    }
}

交点不返回任何行:

        var usersL = new List<User>()
                        {
                            new User{ID = 1,Email = "abc@foo.com"},
                            new User{ID = 2,Email = "def@foo.com"}
                        };

        var usersR = new List<User>()
                        {
                            new User{ID = 1,Email = "abc@foo.com"},
                            new User{ID = 2,Email = "def@foo.com"}
                        };

        var both = (from l in usersL select l)
            .Intersect(from users in usersR select users);

        foreach (var r in both)
            Console.WriteLine(r.Email);