HashSet<T>.RemoveWhere() and GetHashCode()
<p>Aloha,</p>

<p>Here's a simple class that overrides GetHashCode:</p>

<pre><code>class OverridesGetHashCode
{
    public string Text { get; set; }

    public override int GetHashCode()
    {
        return (Text != null ? Text.GetHashCode() : 0);
    }
    // overriding Equals() doesn't change anything, so I'll leave it out for brevity
}
</code></pre>

<p>When I create an instance of that class, add it to a HashSet and then change its Text property, like this:</p>

<pre><code>var hashset = new HashSet&lt;OverridesGetHashCode&gt;();
var oghc = new OverridesGetHashCode { Text = "1" };
hashset.Add(oghc);
oghc.Text = "2";
</code></pre>

<p>then this doesn't work:</p>

<pre><code>var removedCount = hashset.RemoveWhere(c =&gt; ReferenceEquals(c, oghc));
// fails, nothing is removed
Assert.IsTrue(removedCount == 1);
</code></pre>

<p>and neither does this:</p>

<pre><code>// this line works, i.e. it does find a single item matching the predicate
var existing = hashset.Single(c =&gt; ReferenceEquals(c, oghc));
// but this fails; nothing is removed again
var removed = hashset.Remove(existing);
Assert.IsTrue(removed); 
</code></pre>

<p>I guess the hash it internally uses is generated when item is inserted and, if that's true, it's
understandable that hashset.Contains(oghc) doesn't work. 
I also guess it looks up item by its hash code and if it finds a match, only then it checks the predicate, and that might be why the first test fails (again, I'm just guessing here). 
But why does the last test fail, I just got that object out of the hashset? Am I missing something, is this a wrong way to remove something from a HashSet?</p>

<p>Thank you for taking the time to read this.</p>

<p>UPDATE: To avoid confusion, here's the Equals():</p>

<pre><code>protected bool Equals(OverridesGetHashCode other)
    {
        return string.Equals(Text, other.Text);
    }

public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != this.GetType()) return false;
        return Equals((OverridesGetHashCode) obj);
    }
</code></pre>
