title: How does Assert.AreEqual determine equality between two generic IEnumerables?
body: <p>I have a unit test to check whether a method returns the correct <code>IEnumerable</code>.  The method builds the enumerable using <code>yield return</code>.  The class that it is an enumerable of is below:</p>
  
  <pre><code>enum TokenType
  {
      NUMBER,
      COMMAND,
      ARITHMETIC,
  }
  
  internal class Token
  {
      public TokenType type { get; set; }
      public string text { get; set; }
      public static bool operator == (Token lh, Token rh) { return (lh.type == rh.type) &amp;&amp; (lh.text == rh.text); }
      public static bool operator != (Token lh, Token rh) { return !(lh == rh); }
      public override int GetHashCode()
      {
          return text.GetHashCode() % type.GetHashCode();
      }
      public override bool Equals(object obj)
      {
          return this == (Token)obj;
      }
  }
  </code></pre>
  
  <p>This is the relevant part of the method:</p>
  
  <pre><code> foreach (var lookup in REGEX_MAPPING)
   {
       if (lookup.re.IsMatch(s))
       {
           yield return new Token { type = lookup.type, text = s };
           break;
       }
   }
  </code></pre>
  
  <p>If I store the result of this method in <code>actual</code>, make another enumerable <code>expected</code>, and compare them like this...</p>
  
  <pre><code>  Assert.AreEqual(expected, actual);
  </code></pre>
  
  <p>..., the assertion fails.</p>
  
  <p>I wrote an extension method for <code>IEnumerable</code> that is similar to <a href="https://docs.python.org/2/library/functions.html?highlight=zip#zip" rel="noreferrer">Python's <code>zip</code> function</a> (it combines two IEnumerables into a set of pairs) and tried this:</p>
  
  <pre><code>foreach(Token[] t in expected.zip(actual))
  {
      Assert.AreEqual(t[0], t[1]);
  }
  </code></pre>
  
  <p>It worked!  So what is the difference between these two <code>Assert.AreEqual</code>s?</p>