【问题标题】:Form = Form = Form, what does statement do?形式=形式=形式,语句是做什么的?
【发布时间】:2013-04-10 16:27:59
【问题描述】:

我从来没有遇到过这种类型的语句,谁能告诉我它的功能。

Form = CardForm = MainForm;

这是一个桌面应用程序(我一般是桌面应用程序的新手)

谢谢

【问题讨论】:

  • 谢谢大家,这就是我的想法,但我从未见过它是这样编码的。想确保声明没有什么特别之处。
  • 您真的应该花时间学习更多标准命名约定。该代码看起来像一堆类名,而不是一堆变量。
  • @Servy 他们是班级,这是我从被解雇的人那里接手的应用程序 - 所以告诉他.. :)
  • @BuddyMurphy 如果它们是类名而不是变量,那么代码将无法编译。

标签: c# winforms .net-4.0


【解决方案1】:

到目前为止,所有答案都包含细微的错误。让我在这里直接记录。

链式赋值表达式的语义

x = y = z

是:

  • 对第一个表达式 x、y 和 z 求值,并按顺序生成它们的副作用(如果有)。

  • 其次,将 z 求值产生的值转换为与表达式 y 关联的类型。将此值称为 z1。请注意,这可能不是 z 的值;可能涉及转换。

  • 第三,执行将z1分配给y的副作用。

  • 第四,z1 转换为与表达式 x 关联的类型。将此值称为 z2。同样,z2 不必与 z1 或 z 相同。

  • 第五,z2赋值给x。

总结起来,它的语义是:

side effects of x
side effects of y
side effects of z
z1 = value of z converted to type of y
y = z1 
z2 = value of z1 converted to type of x
x = z2

其他一些答案试图告诉您x = y = z; 的语义只是y = z; x = y; 的语义,这是完全错误。在该程序中,y 和 z 的副作用发生在 x 的副作用之前,并且在该程序中,y 是从读取的。在x = y = z; 中这些都不正确。

【讨论】:

    【解决方案2】:

    在 C# 以及许多其他语言中,将值分配给变量的行为本身会返回一个值。这称为表达式的逻辑值(或左值)。

    假设你想设置五个变量:

    int a, b, c, d, e;
    

    到 5 号。你可以这样做:

    a = b = c = d = e = 5;
    

    表达式e = 5 的值为5,将设置为dd = 5 的值为5,将设置为cc = 5 的值为5,将设置为bb = 5 的值为5,将设置为a。然后a 将被设置为5

    由于我们不知道 CardCardFormMainForm 的类型,因此我们无法准确告诉您代码将做什么,因为类型可以定义隐式转换,而重写的赋值运算符可以返回任何感觉的值(当然是那种类型的)。​​

    表达式:

    CardForm = MainForm
    

    对于最终分配给CardForm 的任何东西都有一个逻辑值。最有可能的是,CardForm 将设置为 MainForm 的值,并且该表达式本身将返回 CardFormnew 值,然后将其设置为 Form

    【讨论】:

    • 该表达式将导致 分配给 CardForm 的值不一定是 MainForm 的值。那里可能存在用户定义的转换。
    • @EricLippert - 是的,在我发布答案后,这句话有点让我烦恼。但我想不出更好的方法来解释这不会使答案更难理解。
    • 我注意到你的最后一段是这个答案中第一个真正正确地说明赋值运算符语义的段落。
    • @EricLippert - 是的,做了一些更新以使这个答案更加Eric Lippert Approved
    【解决方案3】:

    假设FormCardFormMainForm 是变量...

    它是2个赋值运算符,赋值运算符的独特之处在于它们是从右到左求值的。

    首先将CardForm 设置为MainForm,然后将Form 设置为CardForm = MainForm 的结果

    【讨论】:

    • 赋值 表达式 -- 不是语句 -- 从左到右 求值,与所有 C# 表达式相同。赋值运算符的副作用从右到左生效。您可以轻松地证明赋值是从左到右评估的:class C { C M() { Console.WL(1); return this; } C N() { Console.WL(2); return this; } int P { get { Console.WL(3); return 4; } set { Console.WL(5); } } 然后执行 c.M().P = c.N().P,您当然会看到 M()N() 之前执行,因为像所有运算符一样,赋值是从左到右评估的。
    • 作业的副作用如您所说,从右到左发生。显然 assignment 直到 双方 都被评估后才会发生,所以分配发生在 权利评估之后。但是操作数的计算是从左到右的。很多人都会犯这个错误,包括写书的人。
    • 总结一下,如果你有x = y = z,那么操作的顺序是首先评估 x,然后是 y,然后是 z,然后将 z 分配给 y,然后是分配给的值y 分配给 x。 (请注意,这不一定是 y 的值!y 可能是易失的并且在另一个线程上变化。或者 y 可能是没有值的只写属性!这里 没有读取 y .) 所以再一次:操作数,从左到右。作业的副作用,从右到左。
    • @EricLippert 你可能想告诉 MSDN 上的人 "When two or more operators that have the same precedence are present in an expression, they are evaluated based on associativity. Left-associative operators are evaluated in order from left to right. For example, x * y / z is evaluated as (x * y) / z. Right-associative operators are evaluated in order from right to left. For example, the assignment operator is right associative. If it were not, the following code would result in an error." - msdn.microsoft.com/en-us/library/ms173145.aspx
    • 好吧,公平地说,该文档的其余部分清楚地表明,按优先级/关联性顺序评估的是 operators,而不是 operands我>。但我同意这一段措辞令人困惑。我会向文档经理提及。
    【解决方案4】:

    鉴于 FormCardFormMainForm 实际上是变量,但由于命名约定不太可能,建议它们使用驼峰式:

    = 运算符可以传递使用,因此该语句等价于(相当粗略,详细请参见https://stackoverflow.com/a/15931435/17713 和 cmets!):

    CardForm = MainForm;
    Form = MainForm;
    

    注意=右操作(分配顺序)。

    = 不能在 C# 中重载。因此,它必须是一项任务,并且这一行没有特定于桌面应用程序的方面。

    另见:http://msdn.microsoft.com/en-us/library/sbkb459w.aspx

    【讨论】:

    • 相当于这个。在原始形式中,CardForm 永远不会被读取。在您所谓的等效形式中,它读取。如果CardForm 是一个完全普通的局部变量,那么您的陈述是正确的,但有很多方法可能不正确;例如,它可能是一个 volatile 字段,但仍然是一个变量。在这种情况下,CardForm 上没有引入读取栅栏。
    • @EricLippert 感谢您指出这一点。在重新阅读文档和接受的答案 + cmets 后,我更正了我的“等效”代码。现在好多了,不是吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-13
    相关资源
    最近更新 更多