简体   繁体   中英

C# foreach unexpected behavior

Why C# compiler allows this to compile and throws runtime exception when run?

class Program
{
   static void Main(string[] args)
   {
      IEnumerable<Test> list = new List<Test>() { new Test() };

      foreach(IDisposable item in list)
      {

      }
   }
}

public class Test
{

}

This does compile with any interface and it doesn't compile if you replace IDisposable with concrete class.

The foreach loop has an implicit cast in it. It's roughly like this:

using (IEnumerator<Test> iterator = list.GetEnumerator())
{
    while (iterator.MoveNext())
    {
        IDisposable item = (IDisposable) iterator.Current;
        // Body of foreach loop here
    }
}

Back before generics, that was much handier than having to cast in the source code. Now it's not so important, but it would be odd for it to not compile. Note that the compiler will check that it's at least feasible . If you use foreach (string item in list) that wouldn't compile, because a Test can't be a string - but a Test can be an IDisposable , because it could refer to an instance of a subclass of Test that implements IDisposable . If you make the Test class sealed, it will fail to compile even with IDisposable , too, because then a Test instance can't implement IDisposable .

Basically, it will compile if a cast from Test to the iteration type would compile, and will fail to compile otherwise. But it'll fail at execution time if a normal cast would fail at execution time, too.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM