Wpadłem na coś, co było dla mnie nieoczekiwanym rezultatem podczas testowania prostej metody rozszerzenia ForEach
.Czy akcja/delegat może zmienić wartość argumentów?
ForEach
metoda
public static void ForEach<T>(this IEnumerable<T> list, Action<T> action)
{
if (action == null) throw new ArgumentNullException("action");
foreach (T element in list)
{
action(element);
}
}
Test
metoda
[TestMethod]
public void BasicForEachTest()
{
int[] numbers = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
numbers.ForEach(num =>
{
num = 0;
});
Assert.AreEqual(0, numbers.Sum());
}
Dlaczego numbers.Sum()
być równa 55 a nie 0?
@ 249076: Tak, to by działało. –
Zgadzam się, co chcę, aby była pętlą for, ale w jaki sposób sprawiłbym, żeby działała w metodzie rozszerzenia, jeśli argument zostanie przekazany przez wartość, gdy zostanie wykonane wezwanie do działania? Nie wygląda na to, że istnieje sposób przekazania wartości przez odniesienie do delegata akcji, który jest przekazywany do funkcji ForEach. Sądzę, że wszyscy o tym wiedzą, ale nie zdawałem sobie sprawy, że foreach (int num in numbers) {num = 0; } nie działa. Dlaczego num jest kopią tymczasową, a nie referencją? W pewnym sensie założyłem, że foreach był po prostu cukrem syntaktycznym dla "za". Chyba muszę przestać robić tak wiele założeń. – 249076
Chciałbym znaleźć sposób, aby napisać rozszerzenie ForEach, aby mógł zmienić wartość int. Nie sądzę, żeby to miało sens, ale jest to zagadka, którą chciałbym rozwiązać. – 249076