CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 7 of 7
  1. #1
    Join Date
    Mar 2007
    Posts
    155

    Problem using List Except

    Code:
     interface IValidationData : IEquatable<IValidationData>
            {
           
            }       
    
            class Customer : IValidationData
            {
                public string Name { get; set; }
                public int Age { get; set; }            
    
                public bool Equals(IValidationData otherValue)
                {
                    Customer other = otherValue as Customer;
    
                    if (!Name.Equals(other.Name))
                        return false;
                    if (!Age.Equals(other.Age))
                        return false;
    
                    return true;
                }
    
                public override int GetHashCode()
                {
                    return Name.GetHashCode() ^ Age.GetHashCode();
                }
            }
    
        List<Customer> list1 = new List<Customer>();
        List<Customer> list2 = new List<Customer>(); 
        List<Customer> list3 = list2.Except(list1).ToList(); 
    // This line is not working why?
    I can't use Except method of List, why?

  2. #2
    Join Date
    Feb 2011
    Location
    United States
    Posts
    1,016

    Re: Problem using List Except

    Without knowing the exact exception, it's hard to tell. Do you have using System.Linq; at the top of your source file? If not, add it.

    The following code compiles for me okay:

    Code:
    List<int> list1 = new List<int>();
    list1.Add(2);
    list1.Add(3);
    
    List<int> list2 = new List<int>();
    list2.Add(2);
    
    List<int> list3 = list1.Except(list2).ToList();
    
    foreach(int i in list3)
        Console.WriteLine(i);
    
    //Prints 3
    You can also try defining list3 like:

    Code:
    IEnumerable<int> diff = list1.Except(list2)
    List<int> list3 = new List<int>(diff);
    However, I'm not sure there is any advantage to doing that.

    If neither of those solves your problem, post the exception message and that might help figure out what is wrong.
    Best Regards,

    BioPhysEngr
    http://blog.biophysengr.net
    --
    All advice is offered in good faith only. You are ultimately responsible for effects of your programs and the integrity of the machines they run on.

  3. #3
    Join Date
    Mar 2007
    Posts
    155

    Re: Problem using List Except

    I'm not getting any exception, it complies. But it's not getting the required values for list1.Except(list2).

    In your example you are using int, so it will work. If you could try with my class pattern, it won't

  4. #4
    Join Date
    May 2007
    Location
    Denmark
    Posts
    623

    Re: Problem using List Except

    I did some debugging on your code. It seems if the objects in list1 are the same instances as the ones in list2, the code works. However, if the objects are different instances with the same values, it does not.

    this works:
    Code:
                List<Customer> list1 = new List<Customer>();
                Customer c = new Customer();
                c.Age = 18;
                c.Name = "Kitten";
                list1.Add(c);
                List<Customer> list2 = new List<Customer>();
                //c = new Customer();
                //c.Age = 18;
                //c.Name = "Kitten";
                list2.Add(c);
                c = new Customer();
                c.Age = 28;
                c.Name = "Mitten";
                list2.Add(c);
                List<Customer> list3 = list2.Except(list1).ToList();
    this does not:
    Code:
                List<Customer> list1 = new List<Customer>();
                Customer c = new Customer();
                c.Age = 18;
                c.Name = "Kitten";
                list1.Add(c);
                List<Customer> list2 = new List<Customer>();
                c = new Customer();
                c.Age = 18;
                c.Name = "Kitten";
                list2.Add(c);
                c = new Customer();
                c.Age = 28;
                c.Name = "Mitten";
                list2.Add(c);
                List<Customer> list3 = list2.Except(list1).ToList();
    This happens despite the fact that the hashcodes appear to be identical. I'm not able to explain this behavior, but I hope this might help
    It's not a bug, it's a feature!

  5. #5
    Join Date
    May 2007
    Posts
    1,546

    Re: Problem using List Except

    You more than likely need to override the default equality method too:

    Code:
    public override bool Equals (object other)
    {
        return Equals (other as Customer);
    }
    www.monotorrent.com For all your .NET bittorrent needs

    NOTE: My code snippets are just snippets. They demonstrate an idea which can be adapted by you to solve your problem. They are not 100% complete and fully functional solutions equipped with error handling.

  6. #6
    Join Date
    Mar 2007
    Posts
    155

    Re: Problem using List Except

    Thank you BioPhyEng, Foamy and Mutant fruit for answers.

    Mutantfruit, Your solution worked.
    Foamy, just found another interesting thing..
    If I change the customer class to -
    class Customer : IEquatable<Customer>
    it's working too...

    Looks like except doesn't want Equals method with parameter as an interface

  7. #7
    Join Date
    May 2007
    Posts
    1,546

    Re: Problem using List Except

    The solution is a little confusing, but hopefully this will be clear enough:

    Code:
    class Person {
        public string Name { get; set; }
    }
    
    // Declare a list
    Person a = new Person { Name = "Bert" };
    Person b = new Person { Name = "Bert" };
    
    List<SomeClass> list = new List<SomeClass> ();
    list.Add (a);
    if (list.Contains (b))
        Console.WriteLine ("We already have bert!");
    If you run this code exactly as is, it will not detect that there is a person called 'Bert' in the list already. If i extend the person class to do:

    Code:
    public override bool Equals (object other)
    {
        if (other is Person)
            return ((Person) other).Name == Name;
    }
    
    public override int GetHashCode ()
    {
        return Name.GetHashCode ();
    }
    The original code will now work. This is because the List<T> implementation will call the regular 'Equals' method to do comparisons. This is why my solution worked.

    However, List<T> is smart! If I create a List<Customer>, the implementation of the 'Contains' method will first check to see if the type (in this case 'Customer') implements IEquatable<Customer>. If it does, it will then invoke the method which is guaranteed to exist:

    IEquatable<Customer>.Equals (Customer other);

    This is why things worked when you had a List<Customer> and made the 'Customer' class implement IEquatable<Customer>.

    Now, the slightly confusing part. In your original code you had a Customer which was essentially an IEquatable<IValidationData>. If you had declared your list as a: List<IValidationData> and added a bunch of Customer classes to it, it would've worked perfectly! This is because List<Customer> only checks for IEquatable<Customer>, it does not check for IEquatable<IValidationData>. Your code failed because you did not invoke the Equals method you had declared and instead fell back to using the default implementation of Equals which just checks to see if the two objects are actually the same piece of memory.

    The solution is simple - whenever you have a custom Equals method, *always* override the basic equals method (as i showed you) and call your specific method. This means that you will always get correct comparisons, no matter how Equals is called or which overload of Equals is initially invoked.
    www.monotorrent.com For all your .NET bittorrent needs

    NOTE: My code snippets are just snippets. They demonstrate an idea which can be adapted by you to solve your problem. They are not 100% complete and fully functional solutions equipped with error handling.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured