2017-03-18 14 views
0

我正试图将int类型的列表中的所有数字平方。但是,当我运行代码时,该列表似乎根本没有改变。无法重新分配LINQ语句中的值

public static List<int> SquareList(List<int> root) 
{ 
    root.ForEach(x => x = x*x); 
    return root; 
} 

x_unit中的测试类。

[Fact] 
public void testSqures() 
{ 
    var input = new List<int> { 1, 2, 3 }; 
    var expected = new List<int> { 1, 4, 9 }; 
    var result = Square.SquareList(input); 

    Assert.Equal(expected,result); 
} 

问题是否foreach运算符没有更改基础对象?

我需要创建一个新列表吗?或者有没有办法将这个列表转换到位?

+1

从MSDN:修改底层集合在'行动的身体'委托是不受支持并导致未定义的行为。 – Vikhram

+0

您正在使用值类型,且值类型无法在“操作”委派中更新。您一定需要创建一个新列表。 – NoviceProgrammer

回答

1

将其更改为

return root.Select(x => x*x).ToList(); 

这不会改变现有的列表,它会创建一个新的列表,并返回它这将是首选。如果您确实想要更新原始列表,请更改签名以传入ref,然后将指针更新为新列表。

public static List<int> SquareList(ref List<int> root) 
{ 
    root = root.Select(x => x*x).ToList(); 
    return root; 
} 

或与使用它的循环

public static List<int> SquareList(List<int> root) 
{ 
    for(int i = 0; i < root.Count; i++) 
     root[i] = root[i]*root[i]; 
    return root; 
} 

ForEach并遍历该列表,如果您有包含一个int引用类型(类),你可以改变这种类型的内部值但你不能重新分配列表中包含的指针。

0

如果要获取集合的新表示形式,请使用Select而不是ForEach。返回新的对象而不是改变它是函数式编程的范例。而LINQ有助于使用这种模式。

0

从MSDN:

修改的行动代表体内的底层集合,不支持并导致不确定的行为。

你应该只使用常规for循环做这样的事情,而不是LINQ或类似功能的语句

public static List<int> SquareList(List<int> root) 
{ 
    for (int i = 0, n = root.Count; i < n; ++i) 
     root[i] = root[i] * root[i]; 
    return root; 
} 
+0

您引用的文档与该问题无关。警告是指修改集合的结构,即去除或插入/添加元素,而不是简单地替换值。 –

+0

@PeterDuniho在尊重的情况下,您是否有任何使用ValueType的官方文档或代码示例来证明您的观点?我认为你在'修改底层集合'和'修改底层集合引用的值'这两个术语之间存在混淆' – Vikhram

+0

如果你试图修改集合,会抛出一个'InvalidOperationException',并且消息_“集合被修改;枚举操作可能不会执行。“_。这是一个完全不同的问题,而不是试图修改一个本身并不是集合的一部分的值类型。代码示例:'List values = new List {0,1,2}; values.ForEach(i => values [i] = i + 1);',抛出异常。不应该使用ForEach()来修改列表是正确的,但是引用文档的特定部分是不正确的,因为它与OP的代码无关。 –