【问题标题】:C# LINQ update item List<string>C# LINQ 更新项列表<string>
【发布时间】:2014-07-30 18:56:49
【问题描述】:

我在更新 List&lt;string&gt; 下使用 LINQ 匹配不同字符串的单个项目时遇到问题。假设我有一个名字列表,我想检查名字“John”是否已经存在于我的列表中。如果是,则将“John”替换为“Anna”。

这是我的工作:

var sItem = myList.First(n=> n == "John"); //I am 100% sure that John exists, that\s why I use .First
sItem = "Anna";

这是它应该如何工作的,但是当我在这个过程之后检查我的列表 (myList) 时,原始项目仍然存在(我仍然可以看到 John,而不是 Anna)。我也尝试在 List 上实现 INotifyChanged,但仍然没有结果。

我做错了什么?

【问题讨论】:

  • 您没有更改列表。你正在改变你的变量。
  • 那我该如何解决呢?
  • 不需要 LINQ:var sItem = myList.IndexOf("John"); myList[sItem] = "Anna";

标签: c# linq


【解决方案1】:

如果需要更新,请使用FindIndex:

int index = myList.FindIndex(n => n == "John");
myList[index] = "Anna";

【讨论】:

    【解决方案2】:

    您正在将 linq 查询的结果分配给字符串变量。那不是列表的元素,而是一个变量,它也引用了该列表的元素。更改变量sItem 的值将定义一个新字符串,该字符串将被sItem 引用,并且列表中的项目保持不变。

    您可以使用FindIndex获取数组中元素的索引,并使用它来引用列表元素。

    int index = myList.FindIndex(n => n == "John");
    myList[index] = "Anna";
    

    搜索与 指定谓词,并返回第一个从零开始的索引 出现在整个列表中。

    编辑

    当一个字符串变量被分配给另一个时。它们都将引用相同的字符串,但是当您将不同的字符串分配给第二个变量时,它们都会引用不同的字符串。请参阅以下来自 Eric Lippert 的 answer 的示例。

    a----------------------Hello
    

    然后你说“b = a”,这意味着将另一段字符串附加到a附加到的同一事物上

    a----------------------Hello
                          /
    b---------------------
    

    然后你说“现在将 b 附加到 Hi”

    a----------------------Hello
    
    b----------------------Hi
    

    【讨论】:

    • 字符串的不变性并不是您不能通过为变量分配不同的字符串来更改列表的原因。
    • 它与不可变没有任何关系。字符串是引用类型。在他的示例中,变量n 只是引用了原始字符串。如果他将 n 分配给一个新字符串,那么 n 只是指一个新的对象/字符串。它与var a = new SomeClass(); var b = a 相同,如果您现在执行b = new SomeClass(),那么您根本没有更改ab 现在只是引用一个新对象。
    • @Adil:“因为它们是不同的对象”仍然不是原因。它们是相同的对象,但变量不同。假设我们有两张纸(变量)。相同的房子地址写在两张纸上(这是每个变量的值,引用)。只有一所房子(对象)。如果有人在一篇论文上写了不同的地址(引用 diff. 对象),另一篇论文不会改变(列表)。
    • 再次感谢您提供了非常好的例子和如此友善。我明白,它是如何工作的,但可能这个词对象造成了混乱。当它们具有相同的值时(当分配查询结果时),它们是对同一对象的不同引用。我试图以更好的方式解释它,请看一下。
    【解决方案3】:
    int index = strList.FindIndex(n => n == "John");
    if (index != -1)
    {
        strList[index] = "Anna";
    }
    

    这将确保如果列表中不存在“John”,程序不会崩溃。

    【讨论】:

      【解决方案4】:

      它应该适合你

      List<string> list = new List<string>(); 
      
      list.Add("Gandarez");
      list.Add("Carlos");
      
      var search = list.FirstOrDefault(l => l == "Carlos");
      
      if (search != null)
      {
          var index = list.IndexOf("Carlos");
          list.RemoveAt(index);
          list.Insert(index, "Test");
      }
      

      【讨论】:

      • 如果一次就足够了,您将对此列表进行两次搜索。
      【解决方案5】:
      int sItem = myList.FindIndex(x => x == "John");
      myList[sItem] = "Anna";
      

      【讨论】:

        【解决方案6】:

        您看到的问题是System.String,虽然实际上是一个引用类型,但它的行为就像一个值类型。因此,当您为 sItem 分配新值时,您是在替换它,而不是更改它。

        如果您使用的是真正的引用类型,那么您尝试的方法可能会奏效:

        List<Person> myList = ....;
        var sItem = myList.First(p=> p.Name == "John");
        sItem.Name = "Anna";
        

        (分配 -- sItem = new Person("Anna"); -- 仍然会以同样的方式失败,)

        【讨论】:

        • 其实它不作为值类型,它作为引用类型。如果你有var a = new SomeClass(5),然后你又做了a = new SomeClass(10),那么你也永远不会改变第一个对象。 a 现在只是指一个新对象。字符串也是如此。 n = "John" 创建一个分配给变量的新字符串。当然,这根本不会影响他列表中的字符串,因为它只是保存对其旧字符串的引用。
        • @DavidRaab - 它确实充当值类型。它是一种引用类型,作用类似于值类型。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-05-15
        • 1970-01-01
        • 2012-10-02
        • 1970-01-01
        • 1970-01-01
        • 2023-03-26
        • 2023-03-15
        相关资源
        最近更新 更多