对于每个列表<;T>;扩展方法-值或引用类型

本文关键字:方法 引用类型 扩展 于每个 列表 lt gt | 更新日期: 2023-09-27 18:22:45

我觉得这很奇怪。我想如果有人能澄清我的疑虑。

var list = new List<SomeClass>();

现在如果我们使用收集的ForEach扩展方法

list.ForEach(c=>c.SomeProperty = SomeValue);

所以现在我们可以得到更新后的值。所以它似乎是引用类型。是的,ForEach取一个Action作为它的引用类型。但是,如果尝试重新初始化ForEach中的对象,我看不到预期的行为。

list.ForEach(c=>{
  if(SomeCondition) // lets consider its always true now.
  {
    c = new SomeClass();
  }
});

所以在这次处决之后,我期待着新的名单。并且不应包含旧对象的引用。但如果我打印清单。我能看到旧的价值观。

那么为什么ForEach没有重新初始化列表中的对象呢?当我们看到ForEach是值类型上的引用类型时

对于每个列表<;T>;扩展方法-值或引用类型

无论c的类型是引用类型还是值类型,在设置变量c = something时,都会覆盖引用的变量。因此,c引用的原始对象不再被引用。不过,这也不会改变列表更新引用的方式,这根本不是它的工作方式。

如果你想用其他东西替换列表中的一些元素,你需要使用Select:

list.Select(c =>
{
    if (SomeCondition)
        return new SomeClass();
    // default case, return the same element
    return c;
}.ToList();

请注意,这会创建一个列表,因此旧列表仍然包含相同的元素。

如果要实际替换原始列表中的元素,则必须通过访问其索引来覆盖列表中的这些元素。你可以用一个普通的for循环:

for (int i = 0; i < list.Count; i++)
{
    if (SomeCondition)
    {
        list[i] = new SomeClass();
    }
}

这实际上会改变现有列表并替换其中的一些元素