なぜC#コンパイラはこれをコンパイルして実行時にランタイム例外をスローするのを許可するのですか?
class Program
{
static void Main(string[] args)
{
IEnumerable<Test> list = new List<Test>() { new Test() };
foreach(IDisposable item in list)
{
}
}
}
public class Test
{
}
これは、任意のインターフェイスでコンパイルされ、IDisposableを具象クラスで置き換えてもコンパイルされません。
foreach
ループには暗黙のキャストがあります。おおよそ次のようになります。
using (IEnumerator<Test> iterator = list.GetEnumerator())
{
while (iterator.MoveNext())
{
IDisposable item = (IDisposable) iterator.Current;
// Body of foreach loop here
}
}
ジェネリックの前に戻ると、ソースコードをキャストするよりもずっと便利でした。今はそれほど重要ではありませんが、コンパイルしないのは奇妙です。コンパイラwillが少なくともfeasibleであることを確認してください。 Test
をstring
にすることはできないため、コンパイルできないforeach (string item in list)
を使用すると、Test
can = IDisposable
になります。これは、Test
を実装するIDisposable
のサブクラスのインスタンスを参照する可能性があるためです。 Test
クラスをシールすると、IDisposable
でもTest
を実装できないため、IDisposable
を使用してもコンパイルに失敗します。
基本的に、Test
から反復型へのキャストがコンパイルされる場合はコンパイルされ、そうでない場合はコンパイルに失敗します。ただし、通常のキャストも実行時に失敗すると、実行時に失敗します。