开发者

A question about comparing List<T>

开发者 https://www.devze.com 2022-12-24 13:16 出处:网络
i have two lists: List<comparerobj> list_c = new List<comparerobj>(); List<comparerobj> list_b = new List<comparerobj>()开发者_开发百科;

i have two lists:

List<comparerobj> list_c = new List<comparerobj>();
List<comparerobj> list_b = new List<comparerobj>()开发者_开发百科;

i'm filling lists somehow

then i'm trying to find elements in list_b which list_c doesnt contain:

foreach (comparerobj b in list_b)
{
    bool lc = !list_c.Contains(b);
    if (lc != true)
    {
        data.Add(b);
    }
}

but for any b i'm getting that lc = true. what am i doing wrong?


This is kinda' a peeve, but lose the temporary bool. It's not a non-doublenegative, and it's confusing:

foreach (comparerobj b in list_b)
{
    if (list_c.Contains(b))
    {
        data.Add(b);
    }
}

Now that you see the simplified logic, it's clear that you're only adding items that are in both lists. A single negative might be useful here:

foreach (comparerobj b in list_b)
{
    if (!list_c.Contains(b))
    {
        data.Add(b);
    }
}


If you're using .NET 3.5 this is simple:

list_b.Except(list_c);

If that's still not calculating equality correctly, the 2nd parameter to Except() is an IEqualityComparer<T> which you can then use to compare your objects however you wish, or you could just override Equals() for your compareobjs.

If you want to put the values into a new list (which is what I gather from the data variable), you can simply do this:

var data = list_b.Except(list_c).ToList();

Edit:

You mention that it doesn't work, and this is likely because you haven't overridden Equals() and GetHashCode() to determine value equality. The easiest way to get your example working is to use implement the IEquatable<T> interface on your CompareObj:

public class CompareObj : IEquatable<CompareObj>
{
    public bool Equals(CompareObj other)
    {
        // example equality, customize for your object
        return (this.ExampleValue.Equals(other.ExampleValue));
    }
}

More information can be found on MSDN: http://blogs.msdn.com/csharpfaq/archive/2009/03/25/how-to-use-linq-methods-to-compare-objects-of-custom-types.aspx


How your objects are compared? By default .NET framework compares objects by references. For Example if you create following class:

class A
{
    string Name { get; set; }
}

and follwing code

A a1 = new A() { Name = "a" };
A a2 = new A() { Name = "a" };

then you will find that these objects are different.

You need to override Equals method for .NET Framework to treat above objects as equal.


You've inverting the boolean twice. Once on the first line when you do !list_... and once on the second when you do lc != true.

Try this instead:

bool itemExistsInC = list_c.Contains(b);
if (!itemExistsInC){


You're using the ! operator twice. Also, you don't need to explicitly delcare the bool, in this context. Try this:

foreach (object b in list_b)
{
    if (!list_c.Contains(b))
    {
        data.Add(b);
    }
}


Using linq

list_b.Except(list_c).ToList().ForEach(data.Add);

but for any b i'm getting that lc = true. what am i doing wrong?

One or more of the following:

  • Your sets are entirely different.
  • comparerobj needs to overload the Equals() method
  • The logic you are using is confusing and doesn't work as intended.

If you only want elements in list_b that are not in list_c:

foreach (comparerobj b in list_b)
{
    if (!list_c.Contains(b))
    {
        data.Add(b);
    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号