使用ToUpper函数时,列表元素不会更改

时间:2013-08-30 14:46:11

标签: c# list collections

我想将列表元素更改为大写。但是这段代码会出错。你能帮助我吗?

List<string> fruit = new List<string>();
fruit.Add("apple");
fruit.Add("cherry");
fruit.Add("orange");

fruit.ForEach(
    delegate(string s)
        {
            s = s.ToUpper();
        }
    );
fruit.ForEach(

    delegate(string s)
    {
        Console.WriteLine(s);
    }
   );

6 个答案:

答案 0 :(得分:1)

字符串是不可变的 - ToUpper不会更改字符串 - 创建一个新字符串。原始水果列表仍然引用旧字符串 - 您的ForEach / ToUpper()代码无效。

您需要删除旧字符串并从水果中添加新字符串,或者更好的是IMO,将整个列表重新投影到新列表中,然后可以分配新的水果列表,

fruit = fruit.Select(s => s.ToUpper()).ToList();
fruit.ForEach(s => Console.WriteLine(s));

答案 1 :(得分:1)

试试这个

List<string> fruit = new List<string>();
fruit.Add("apple");
fruit.Add("cherry");
fruit.Add("orange");
fruit = fruit.Select(x=> x.ToUpper()).ToList();
fruit.ForEach(delegate(string s)
                    {
                        Console.WriteLine(s);
                    }
              );

注意:如上面的注释所示,代码将创建一个新的List并分配给fruit变量。如果您不想替换fruit变量,请尝试以下操作。

var upperList = fruit.Select(x => x.ToUpper());
fruit.Clear();
fruit.AddRange(upperList);
  

字符串是不可变的 - 创建对象后无法更改字符串对象的内容,尽管语法使其看起来好像可以执行此操作。例如,当您编写此代码时,编译器实际上会创建一个新的字符串对象来保存新的字符序列

string b = "h";
b += "ello";

来自Msdn

答案 2 :(得分:0)

string是不可变的。您应该在for循环中执行此操作:

List<string> fruit = new List<string>();

fruit.Add("apple");
fruit.Add("cherry");
fruit.Add("orange");

for(int i = 0; i < fruit.Count; i++)
{
    fruit[i] = fruit[i].ToLower();
}

或者您可以使用正确的项目创建新的List<string>并替换fruit引用:

fruit = fruit.Select(x => x.ToLower()).ToList();

答案 3 :(得分:0)

尝试使用for循环

List<string> fruit = new List<string>();
            fruit.Add("apple");
            fruit.Add("cherry");
            fruit.Add("orange");

            for( int i = 0; i < fruit.Count; i++ ) {

                Console.WriteLine(fruit[i].ToUpper()); // To Check
            }

答案 4 :(得分:0)

fruit = fruit.Select(x => x.ToUpper()).ToList();

最好将元素投射到新列表中。没有理由使用委托使代码变得丑陋。只需使用lambda语法:

fruit.ForEach(s => Console.WriteLine(s));

或者

foreach(var s in fruit)
    Console.WriteLine(s);

答案 5 :(得分:0)

首先,让我们首先注意s.ToUpper()实际上并没有改变s。这是不可能的,因为C#中的字符串是不可变的,因为许多其他答案都提到了。我假设你知道这件事,因为你做了s = s.ToUpper()

List包含对项目的引用。

ForEach为您提供这些引用的副本(在这种情况下存储在s中)。

重新分配s时,您不会更改原始参考,只会更改副本s

如果你要修改s(即s.someModifyingFunction())(而不是重新分配它,即s = ...),因为s引用与原始引用相同的对象,这实际上会改变清单。

使用MarcinJuraszek提到的简单的常规for循环应该可以工作:

for(int i = 0; i < fruit.Count; i++)
    fruit[i] = fruit[i].ToUpper();

想象一下,想一想:

对象是书籍。

该列表包含一群学生,他们每个人都指着一本书。

当你ForEach时,你会得到一名新学生与该名单中的一名学生指向同一本书。

当您重新分配s时,您要求新学生指向另一本书。列表中的学生仍然指向与以前相同的书。

当你修改s时,你会在书中写(因为它是同一本书,列表中的学生仍会指向带有这些变化的书)。