试图分配给C#' foreach迭代变量'生成编译时错误。在Linq [IEnumerable] .ForEach(...)中这样做不会。为什么?

时间:2016-08-17 12:31:31

标签: c# linq foreach runtime

我注意到我认为C#和Linq今天在尝试使类更整洁并删除for循环时出现奇怪的行为,用于初始化字符串数组。

我的原始代码:

    for(int i = 0; i < tagCount; i++)
    {
        myObj.tags[i] = string.Empty;
    }

众所周知,值不能分配给C#foreach循环中的迭代变量。例如,下面会生成编译时错误(其中myObj是一个对象,其中包含一个名为&#39; tags&#39;的字符串数组):

    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值没有变化。

这让我感到奇怪,因为没有产生任何错误 - 它似乎什么也没做。这是设计的吗?疏忽?

感谢大家的任何意见。

(PS我知道ToList()。ForEach()的性能损失。我只想看看是否可以删除for循环。我现在对编译过程中出现的行为背后的原因更感兴趣运行时)。

1 个答案:

答案 0 :(得分:3)

是的,它什么也没做 - 但是很多情况都是在C#中发生的。它不清楚你认为它是一个错误,或者你期望它实现的目标。基本上你的lambda表达式是写这样一个方法的简写:

static void Foo(string s)
{
    s = string.Empty;
}

这不是一种有用的方法,但它是完全有效的方法。为列表中的每个值调用它并不会使它更有用。

分配回一个值参数(而不是refout参数)并且不再从参数读取基本上没有意义,但是有效。

在删除循环方面 - 您可以做的一件事是编写扩展方法:

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("");