1

I had two List of class myListClass Where

public class myListclass
{
    public Nullable<decimal> ClassId { get; set;}
    public Nullable<decimal> SectionId { get; set; }
    public Nullable<decimal> MediumId { get; set; }
    public Nullable<decimal> StreamId { get; set; }
    public Nullable<decimal> ShiftId { get; set; }
}  

where list1 is

List<myListclass> liAll = new List<myListclass>();   

and items in liAll are

ClassId Section MediumId Stream  Shift
73     220       207    145       128
73     221       207    145       128
73     222       207    145       128
74     220       207    145       128
74     221       207    145       128
75     220       207    145       128
75     221       207    145       128
76     220       207    145       128
76     221       207    145       128
77     220       207    145       128
77     221       207    145       128
78     220       207    145       128  

And list2 is

List<myListclass> liJoin = new List<myListclass>(); 

Where item in liJoin are

ClassId Section MediumId Stream  Shift
73     220       207    145       128
73     221       207    145       128  

Now I want to select only those items into a list which are in liAll but not in liJoin

So wrote the following code:

List<myListclass> liFinal = new List<myListclass>(); 
liFinal = liAll.Where(w => !liJoin.Contains(w)).ToList();  

but liFinal not giving me accurate result it gives all items of liAll
So my questions are

  1. what's wrong with above code ?
  2. Better way to do this

    Updated code

    liFinal = liAll.Where(w => !liJoin.Select(s => s.ClassId ).Contains(w.ClassId) &&
    !liJoin.Select(s => s.MediumId ).Contains(w.MediumId) &&
    !liJoin.Select(s => s.SectionId ).Contains(w.SectionId) &&
    !liJoin.Select(s => s.ShiftId).Contains(w.ShiftId) &&
    !liJoin.Select(s => s.StreamId).Contains(w.StreamId)).ToList();

Amit Bisht
  • 4,870
  • 14
  • 54
  • 83

4 Answers4

3

First off, you can use the LINQ Except method to get the missing elements:

List<myListclass> liFinal = liAll.Except(liJoin).ToList();  

For this (and other equality-based operations) to work, you need to implement IEquatable<T> on your class:

public class myListclass : IEquatable<myListclass>
{
    public Nullable<decimal> ClassId { get; set; }
    public Nullable<decimal> SectionId { get; set; }
    public Nullable<decimal> MediumId { get; set; }
    public Nullable<decimal> StreamId { get; set; }
    public Nullable<decimal> ShiftId { get; set; }

    public bool Equals(myListclass other)
    {
        return
            other != null &&
            this.ClassId == other.ClassId &&
            this.SectionId == other.SectionId &&
            this.MediumId == other.MediumId &&
            this.StreamId == other.StreamId &&
            this.ShiftId == other.ShiftId;
    }

    public override bool Equals(object obj)
    {
        return this.Equals(obj as myListclass);
    }

    public override int GetHashCode()
    {
        // https://stackoverflow.com/a/263416/1149773
        unchecked
        {
            int hash = 17;
            hash = hash * 23 + ClassId.GetHashCode();
            hash = hash * 23 + SectionId.GetHashCode();
            hash = hash * 23 + MediumId.GetHashCode();
            hash = hash * 23 + StreamId.GetHashCode();
            hash = hash * 23 + ShiftId.GetHashCode();
            return hash;
        }
    }
}  

The implementation for the GetHashCode() method is adapted from this answer by Jon Skeet.

Community
  • 1
  • 1
Douglas
  • 53,759
  • 13
  • 140
  • 188
  • Except returning Null – Amit Bisht Jan 13 '14 at 12:00
  • I suppose this one is easier then `operator overloading`, by the way; thanks for sharing that useful link, i wasn't aware of that post – Saro Taşciyan Jan 13 '14 at 12:03
  • 1
    @Zefnus: I agree with your addition of a proper hyperlink to the `GetHashCode` answer, but I've reverted your removal of the URL from the code. If someone chooses to copy-and-paste the code, I'd rather they copied the URL too. – Douglas Jan 13 '14 at 12:12
  • @Douglas You'r right, i didn't think that way. And now with the last edit it's perfect. Thanks – Saro Taşciyan Jan 13 '14 at 12:14
0

You need to override Equals method for your class MyListClass.

Follow this link. This will tell you how to implement this for your class.

http://msdn.microsoft.com/en-us/library/dd183755.aspx

Here is the snipped which I use for overriding equal methods.

public override bool Equals(object obj)
{
    return Equals(obj as $className$);
}
internal bool Equals($className$ other)
{
    // If parameter is null, return false. 
    if (ReferenceEquals(other, null))
        return false;

    // Optimization for a common success case. 
    if (ReferenceEquals(this, other))
        return true;

    return // TODO: compare this.Memeber1 == other.Member2,
    // if equal return true,
}
fhnaseer
  • 7,159
  • 16
  • 60
  • 112
0

Have you tried using Enumerable.Except();

liFinal = liAll.Except(liJoin);

Here for more

Saro Taşciyan
  • 5,210
  • 5
  • 31
  • 50
noisyass2
  • 580
  • 4
  • 13
  • @wudzik have you seen the link? it contains implementations for both overloads of the Enumerable.Except.. including IEqualityComparer – noisyass2 Jan 13 '14 at 12:03
  • It is not an answer because error was not using Contains instead of Except, but not implementing `Equals` – Kamil Budziewski Jan 13 '14 at 12:05
  • @wudzik i know. thats why i pointed him to msdn article on what to do and didnt provide a specific code example. Zefnus did that, not me. I wanted him to figure it out using the docs – noisyass2 Jan 13 '14 at 12:07
0

Use:

var list = liAll.Except(liJoin);