尝试分配给 C# 'foreach iteration variable' 会生成编译时错误。在 Linq [IEnumerable].ForEach(...) 中这样做不会。为什么?
Attempting to assign to a C# 'foreach iteration variable' generates a compile time error. Doing so in a Linq [IEnumerable].ForEach(...) does not. Why?
今天,当我试图使 class 更整洁并删除用于初始化字符串数组的 for 循环时,我注意到我认为 C# 和 Linq 中的奇怪行为。
我的原码:
for(int i = 0; i < tagCount; i++)
{
myObj.tags[i] = string.Empty;
}
众所周知,在 C# foreach 循环中无法将值分配给迭代变量。例如,以下代码会生成编译时错误(其中 myObj 是一个包含名为 'tags' 的字符串数组的对象):
foreach(string s in myObj.tags)
{
s = string.Empty;
}
Gives: "Cannot assign to 's' because it is a 'foreach iteration variable'"
但是执行以下操作可以正确编译:
myObj.tags.ToList().ForEach(s => s = string.Empty);
我的问题是为什么这个语法编译没有任何问题?
注意:奇怪的行为 - 可能是错误? - 以下
作为后续,我认为确实值得注意的是,当 Linq 方法编译时,在 运行 期间,命令 s=string.Empty
的效果是看不到的,也不会生成 运行 时间错误。 string.Empty
可以替换为任何值,检查 myObj.tags
数组中的任何索引都将显示空值。中断并进入 ...ForEach(s=>s=string.Empty)
显示该行按预期执行,但 s.
的值没有变化
这让我觉得很奇怪,主要是因为也没有产生任何错误——它似乎什么也没做。这是设计使然吗?疏忽?
感谢大家的任何意见。
(P.S。我知道 ToList().ForEach() 的性能影响。我只是想看看我是否可以删除那个 for 循环。我现在对原因更感兴趣在编译和 运行 时间)期间表现出的行为背后)。
是的,它什么都不做 - 但在 C# 中有很多情况会发生这种情况。目前尚不清楚您希望它在哪里出现错误,或者您希望它实现什么。基本上你的 lambda 表达式是一个 shorthand 用于编写这样的方法:
static void Foo(string s)
{
s = string.Empty;
}
这不是一个有用的方法,但它是一个完全有效的方法。为列表中的每个值调用它不会使它更有用。
重新分配给值参数(而不是 ref
或 out
参数)并且不再从参数中读取基本上没有意义,但有效。
在删除循环方面——您可以做的一件事是编写一个扩展方法:
public static void ReplaceAll<T>(this IList<T> list, T value)
{
// TODO: Validation
for (int i = 0; i < list.Count; i++)
{
list[i] = value;
}
}
那么您可以拨打:
myObj.tags.ReplaceAll("");
今天,当我试图使 class 更整洁并删除用于初始化字符串数组的 for 循环时,我注意到我认为 C# 和 Linq 中的奇怪行为。
我的原码:
for(int i = 0; i < tagCount; i++)
{
myObj.tags[i] = string.Empty;
}
众所周知,在 C# foreach 循环中无法将值分配给迭代变量。例如,以下代码会生成编译时错误(其中 myObj 是一个包含名为 'tags' 的字符串数组的对象):
foreach(string s in myObj.tags)
{
s = string.Empty;
}
Gives: "Cannot assign to 's' because it is a 'foreach iteration variable'"
但是执行以下操作可以正确编译:
myObj.tags.ToList().ForEach(s => s = string.Empty);
我的问题是为什么这个语法编译没有任何问题?
注意:奇怪的行为 - 可能是错误? - 以下
作为后续,我认为确实值得注意的是,当 Linq 方法编译时,在 运行 期间,命令 s=string.Empty
的效果是看不到的,也不会生成 运行 时间错误。 string.Empty
可以替换为任何值,检查 myObj.tags
数组中的任何索引都将显示空值。中断并进入 ...ForEach(s=>s=string.Empty)
显示该行按预期执行,但 s.
这让我觉得很奇怪,主要是因为也没有产生任何错误——它似乎什么也没做。这是设计使然吗?疏忽?
感谢大家的任何意见。
(P.S。我知道 ToList().ForEach() 的性能影响。我只是想看看我是否可以删除那个 for 循环。我现在对原因更感兴趣在编译和 运行 时间)期间表现出的行为背后)。
是的,它什么都不做 - 但在 C# 中有很多情况会发生这种情况。目前尚不清楚您希望它在哪里出现错误,或者您希望它实现什么。基本上你的 lambda 表达式是一个 shorthand 用于编写这样的方法:
static void Foo(string s)
{
s = string.Empty;
}
这不是一个有用的方法,但它是一个完全有效的方法。为列表中的每个值调用它不会使它更有用。
重新分配给值参数(而不是 ref
或 out
参数)并且不再从参数中读取基本上没有意义,但有效。
在删除循环方面——您可以做的一件事是编写一个扩展方法:
public static void ReplaceAll<T>(this IList<T> list, T value)
{
// TODO: Validation
for (int i = 0; i < list.Count; i++)
{
list[i] = value;
}
}
那么您可以拨打:
myObj.tags.ReplaceAll("");