【问题标题】:Why is "someString += AnotherString = someString;" valid in C#为什么是“someString += AnotherString = someString;”在 C# 中有效
【发布时间】:2010-09-02 18:09:32
【问题描述】:

我今天正在编写一些代码,当我在另一台显示器上的屏幕上按 alt-tab 键检查某些内容时,我正处于中线。当我回头看时,ReSharper 已将第 3 行着色为灰色,并附注“分配的值未在任何执行路径中使用”。

var ltlName = (Literal) e.Item.FindControl("ltlName");
string name = item.FirstName;
name += 

ltlName.Text = name;

我很困惑;这段代码肯定无法编译。但它确实如此,而且它也在运行。 "name +=" 行对字符串没有影响(我可以说)。这是怎么回事?

(Visual Studio 2008,.NET 3.5)

【问题讨论】:

  • 你有两台显示器,炫耀......
  • +1 用于发布您问题的所有相关代码,而不是多或少一行。
  • @Baddie,我也是。可能会增加三分之一。只是'因为。
  • @Baddie 对不起,不是幸灾乐祸!
  • @Task 好吧,如果我只是像我最初计划的那样发布“name +=”,这个问题就不太清楚了。

标签: c# .net-3.5


【解决方案1】:

请注意,换行符在 C# 中并不特殊。因为下面这行,编译器的完整语句是

name += ltlName.Text = name;

这是一个有效的语句(它将name 分配给ltlName.Text,然后将其附加到name。)

【讨论】:

  • 没错。这(大致)扩展为:ltlName.Text = name; name = name + ltlName.Text;那个等价于ltlName.Text = name; name = name + name;
  • 这是有道理的......我在别处用这段代码测试了它:string x = "This is a string!"; MessageBox.Show(x); x += MessageBox.Show(x); 但这也“隐藏”了我错过的任务。谢谢!
【解决方案2】:

它正在这样做:

name += ltlName.Text = name;

或者让它更清楚一点:

name += (ltlName.Text = name);

属性设置器的结果是设置的值,所以它的工作方式有点像这样:

string tmp = name;
ltlName.Text = tmp;
name += tmp;

当您涉及不同的变量时,观察这一点会更简单,并且只是作为最后一步的简单赋值而不是复合赋值。这是一个完整的例子:

using System;

class Test
{
    public string Text { get; set; }

    static void Main()
    {
        Test t = new Test();

        string x = t.Text = "Hello";
        Console.WriteLine(x); // Prints Hello
    }
}

简单赋值规则(第 7.17.1 节)用于确定表达式的结果:

简单赋值的结果 表达式是分配给的值 左操作数。结果有 与左操作数相同的类型并且是 总是归类为一个值。

所以ltlName.Text = name 的类型与ltlName.Text 的类型相同,并且值是已分配的值。它是一个属性而不是字段或局部变量这一事实并没有改变这一点。

【讨论】:

  • 连接不会创建更多类似于 namename 的东西吗?还是操作顺序抵消了concat?
  • @Joel:不,它仍在执行连接 - 分配版本只是为了让事情变得更简单。将编辑澄清。
  • @Jon Skeet - 在您的澄清中,不应该是 string x += t.Text = "Hello"; (每个 OP)并且该行的结果不会打印“HelloHello”吗?
  • @Joel:不。重点是展示一个更简单的版本,它只是对一个新变量进行赋值——保持三个方面分开。您不能执行“string x+= ...”,因为没有现有值。
  • 可能值得注意的是,像这样在一个表达式中执行多个赋值的代码很难阅读,通常应该避免。 (事实是它令人困惑以至于发布了一个关于它的问题就是证明!)
【解决方案3】:

在 C# 中,换行符不会终止语句 - 只有分号可以。所以下面这行代码正在执行:

name += ltlName.Text = name;

【讨论】:

    【解决方案4】:

    因为空格在 C# 中无关紧要,所以第 3、4 和 5 行形成一个语句:

    name += ltlName.Text = name;
    

    【讨论】:

      【解决方案5】:

      正如预期的那样,结果是连接到自身的名称。所以你得到“namename”。

      obj.Text 只是一个属性,因此该行最终转换为

      //name += obj.Text = name;
      obj.setText(name);
      name += obj.Text;
      

      下面的完整源代码

      public class Program
      {
          public static void Main(string[] args)
          {
              MyClass obj = new MyClass();
              string name = "name";
              name += obj.Text = name;
              Console.Write(name); //prints namename
          }
      }
      

      【讨论】:

        【解决方案6】:

        它正在影响字符串,但直到在字符串用于影响显示上的文字之后。正如 KennyTM 所指出的,这两行都构成了一个语句。与 VB 不同,回车不会结束 C# 中的语句。分号可以。所以这里发生的事情是字符串被设置为文字,并且该操作的结果(可能是“true”?或者只是字符串本身?我不记得)被附加到字符串。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-05-15
          • 2012-09-15
          • 2014-01-05
          • 2015-06-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多