Тема: [Вирішено] foreach цикл, не очікувана поведінка компілятора
Я писав код (багато коду, дописував старий проект), і в кількох місцях допустив помилку: використав не правильний тип даних в foreach; і я довго не помічав цієї помилки, бо був впевнений що якби тип був не правильний, то середовище кинуло би мені помилку на етапі компіляції. Помилки компіляції не було, і я продовжував розробку.
Але сьогодні я рефакторив старий код, і помітив що відбувається щось дивне: цикл foreach проходить по всіх елементах колекції використовуючи тип, якого в колекції не є. Приклад:
IEnumerable<TypeA> collection = new TypeA[] { ... };
foreach(TypeB item in collection) { ... }
Типи TypeA і TypeB не мають прямого звязку (наслідуваня або агрегації).
В процесі виясненя чому компілятор не кидає помилку, шляхом видаленя кусків коду з struct TypeA і з struct TypeB, я виявив що оператор приведеня типів (operator TypeB(TypeA a)) має значний вплив на foreach. І не важливо який він (implicit чи explicit).
Щоб ви могли відтворити проблему, я підготував простий приклад:
using System;
using System.Collections.Generic;
namespace ForEachLoop_Test {
public struct A {
public int Value { get; set; }
public static explicit operator A(int i) { return new A() { Value = i }; }
}
public static class Program {
public static void Main(string[] args) {
IEnumerable<int> collection = new int[] { 1, 2, 3 };
foreach(A item in collection)
Console.Write("{0} ", item.Value);
}
}
}
Як розробник я очікую що компілятор кине помилку в рядку з foreach, бо має бути одне з двох: або int item; або IEnumerable<A> collection.
Але він цього не робить, спокійно компілює цей код, і навіть попередженя (warning) не кидає.
Якого х.. ? Я ж спеціально не додавав implicit щоб будь-які приведеня робити тільки явно, без "магії".
Чому така поведінка в C# ? І чи можливо залишити явне (explicit) приведеня типів і отримувати помилки компіляції користуючи foreach з не правильними типами ?