Czasem korzystam z podobnego kawałka kodu, czyli wyszukanie elementu o danym id i zmiana któregoś pola (pól) w tym elemencie.
class OrderDetails { public int Id; public DateTime Date; } private void Bar(IEnumerable<OrderDetails> orders, int id, DateTime newDate) { foreach (var item in orders) { if (item.Id == id) item.Date = newDate; } }
Nic szczególnego. Gdy jednak zmienimy OrderDetails z klasy na strukturę otrzymamy poniższy błąd kompilacji.
struct OrderDetails { public int Id; public DateTime Date; } private void Bar(IEnumerable<OrderDetails> orders, int id, DateTime newDate) { foreach (var item in orders) { if (item.Id == id) ;// item.Date = newDate; // Error: Cannot modify members of 'item' because it is a 'foreach iteration variable' } }
Kompilator C# bardzo sensownie ostrzegł nas że jest to tylko zmienna lokalna. Co za tym idzie, nie ma sensu przypisywać coś do któregoś jej pola w ten sposób. Bardzo zawiódł mnie kompilator Visual Basic’a który poniższy kod kompiluje. Niestety przypisanie
item.[Date] = newDate
nie zmieni nam nic w kolekcji po której iterujemy. Jeden raz dałem się tak właśnie złapać w VB.
Structure OrderDetails '! struktura Public Id As Integer Public [Date] As DateTime End Structure Private Sub Bar(orders As IEnumerable(Of OrderDetails), id As Integer, newDate As DateTime) For Each item As OrderDetails In orders If item.Id = id Then item.[Date] = newDate ' w tym miejscu zmienimy tylko lokalna zmienna (na stosie) item End If Next End Sub