249*_*076 5 c# linq foreach extension-methods anonymous-function
在测试一个简单的ForEach扩展方法时,我遇到了一个意想不到的结果.
ForEach 方法
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);
}
}
Run Code Online (Sandbox Code Playgroud)
Test 方法
[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());
}
Run Code Online (Sandbox Code Playgroud)
为什么numbers.Sum()等于55而不是0?
num是您正在迭代的当前元素的值的副本.所以你只是在改变副本.
你做的基本上是这样的:
foreach(int num in numbers)
{
num = 0;
}
Run Code Online (Sandbox Code Playgroud)
当然你不希望这改变阵列的内容?
编辑:你想要的是这个:
for (int i in numbers.Length)
{
numbers[i] = 0;
}
Run Code Online (Sandbox Code Playgroud)
在您的特定情况下,您可以在ForEach扩展方法中维护一个索引,并将其作为第二个参数传递给该操作,然后像这样使用它:
numbers.ForEachWithIndex((num, index) => numbers[index] = 0);
Run Code Online (Sandbox Code Playgroud)
但是一般情况下:创建修改应用它们的集合的Linq样式扩展方法是坏样式(IMO).如果你编写了一个不能应用于你的扩展方法,IEnumerable<T>你应该真正考虑它,如果你真的需要它(特别是当你写的是为了修改集合).你没有太大的收获,但很多东西松散(像意想不到的副作用).我确信有例外,但我坚持这条规则并且它对我很有帮助.
| 归档时间: |
|
| 查看次数: |
1389 次 |
| 最近记录: |