变量自行更改?

Variable changing on its own?

提问人:SNBS 提问时间:11/12/2023 更新时间:11/13/2023 访问量:79

问:

看看这个 GIF 就知道了 — 你能看到一个改变 值的语句吗?j

https://imgur.com/a/tjDmstd

如果需要,这是我的代码:

for (int j = 0; j < types[i].GenericParameters.Count(); j++)
{
    // typeDocs is XElement
    // types[i].GenericParameters is a collection of objects (classes) with properties Name and Description

    string value = FindElementValueByName(typeDocs, "typeparam",
        types[i].GenericParameters.ElementAt(j).Name);
    types[i].GenericParameters = types[i].GenericParameters.Select((p, index) =>
    {
        if (index == j) p.Description = value;
        return p;
    });
}

方法如下:FindElementValueByName

private string FindElementValueByName(XElement root, string searchFor, string compareTo)
{
    return root.Elements(searchFor).FirstOrDefault(p =>
    {
        string? name = p.Attribute("name")?.Value;
        if (name == null) return false;
        return name == compareTo;
    })?.Value ?? string.Empty;
}

真正让我惊奇的是,它是一个结构(),因此在传递给方法或任何地方时不应更改!jint

仅供参考:我知道这句话在这里并不是真的必要。我尝试使用,但未设置Description属性。在我当前的代码中,它仍然没有设置在 之后。Selecttypes[i].GenericParameters.ElementAt(j).Description = value;Select

C# LINQ

评论

3赞 Peppermintology 11/12/2023
你的循环正在改变 的值,正如人们所期望的那样 ()。forjj++
0赞 SNBS 11/12/2023
你看过GIF吗?其值在下一次迭代之前会发生变化。
0赞 Gert Arnold 11/13/2023
这是一个调试项目。在正常执行中,永远不会到达该行,因为未执行该语句。这就是为什么永远不应该在 Select 语句中改变对象的原因之一。if (index == j)Select
1赞 Gert Arnold 11/13/2023
是的,赋值不会执行它。在某处完成某项操作之前,不会执行 .当它被执行,如果在 lambda 语句中捕获了该值,它将与该值一起执行。所有这些都使代码难以预测,即有错误。在使用 LINQ 语句时始终牢记不可变性。不要为了让它“工作”而执行。types[i].GenericParameters.ToList()SelectjSelect
0赞 SNBS 11/15/2023
@GertArnold 一个小问题:如果我在问题中使用 as 而不改变原始序列中的对象,而是返回从现有对象创建的新对象(以您处理记录的方式)是否会有潜在危险?Select

答:

1赞 György Kőszeg 11/13/2023 #1

您捕获传递给 的 lambda,它有一个惰性计算。如果您使用代码分析器或 ReSharper,则必须获得有关其可能副作用的一些警告。jSelect

在您的记录中没有第二次迭代(可能是因为该类型只有 1 个泛型参数,但我们看不到),因此您已经离开了传递给 的 lambda 正在执行时,但到那时已经有了它的最终值。forSelectj

如果通过附加 或 来强制立即评估 ,则可能是一个修补程序。Select.ToList()..ToArray()

评论

0赞 SNBS 11/13/2023
谢谢!我忘记了延迟执行:(