Note that there are some explanatory texts on larger screens.

plurals
  1. POLINQ Except operator and object equality
    primarykey
    data
    text
    <p>Here is an interesting issue I noticed when using the <code>Except</code> Operator: I have list of users from which I want to exclude some users:</p> <p>The list of users is coming from an XML file:</p> <p> </p> <p></p> <p>The code goes like this:</p> <pre><code>interface IUser { int ID { get; set; } string Name { get; set; } } class User: IUser { #region IUser Members public int ID { get; set; } public string Name { get; set; } #endregion public override string ToString() { return ID + ":" +Name; } public static IEnumerable&lt;IUser&gt; GetMatchingUsers(IEnumerable&lt;IUser&gt; users) { IEnumerable&lt;IUser&gt; localList = new List&lt;User&gt; { new User{ ID=4, Name="James"}, new User{ ID=5, Name="Tom"} }.OfType&lt;IUser&gt;(); var matches = from u in users join lu in localList on u.ID equals lu.ID select u; return matches; } } class Program { static void Main(string[] args) { XDocument doc = XDocument.Load("Users.xml"); IEnumerable&lt;IUser&gt; users = doc.Element("Users").Elements("User").Select (u =&gt; new User { ID = (int)u.Attribute("id"), Name = (string)u.Attribute("name") } ).OfType&lt;IUser&gt;(); //still a query, objects have not been materialized var matches = User.GetMatchingUsers(users); var excludes = users.Except(matches); // excludes should contain 6 users but here it contains 8 users } } </code></pre> <p>When I call <code>User.GetMatchingUsers(users)</code> I get 2 matches as expected. The issue is that when I call <code>users.Except(matches)</code> The matching users are not being excluded at all! I am expecting 6 users ut "excludes" contains all 8 users instead.</p> <p>Since all I'm doing in <code>GetMatchingUsers(IEnumerable&lt;IUser&gt; users)</code> is taking the <code>IEnumerable&lt;IUser&gt;</code> and just returning the <code>IUsers</code> whose ID's match( 2 IUsers in this case), my understanding is that by default <code>Except</code> will use reference equality for comparing the objects to be excluded. Is this not how <code>Except</code> behaves?</p> <p>What is even more interesting is that if I materialize the objects using <code>.ToList()</code> and then get the matching users, and call <code>Except</code>, everything works as expected!</p> <p>Like so:</p> <pre><code>IEnumerable&lt;IUser&gt; users = doc.Element("Users").Elements("User").Select (u =&gt; new User { ID = (int)u.Attribute("id"), Name = (string)u.Attribute("name") } ).OfType&lt;IUser&gt;().ToList(); //explicity materializing all objects by calling ToList() var matches = User.GetMatchingUsers(users); var excludes = users.Except(matches); // excludes now contains 6 users as expected </code></pre> <p>I don't see why I should need to materialize objects for calling <code>Except</code> given that its defined on <code>IEnumerable&lt;T&gt;</code>?</p> <p>Any suggesstions / insights would be much appreciated.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload