`
RednaxelaFX
  • 浏览: 3015387 次
  • 性别: Icon_minigender_1
  • 来自: 海外
社区版块
存档分类
最新评论

C#的+=运算符两例

    博客分类:
  • C#
阅读更多
刚偶尔看到了justjavac写的java解惑 - 半斤八两(一)java解惑 - 半斤八两(二)。里面提到了Java的复合赋值运算符的两个陷阱:1) 复合赋值运算符有强制类型转换的语义;2) += 左侧必须是原始类型中的数字类型,或者是String类型。

JLS3e如是说:
Java Language Specification, 3rd Edition 写道
15.26.2 Compound Assignment Operators

A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T)((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once.

核心就这么一句,后面还有一堆细节规定,有兴趣可以到官网阅读:JLS3e: 15.26.2 Compound Assignment Operators
读下来,只有当复合赋值运算符的左手边是数组,且数组元素类型是String时才有提到特别针对String的+=,在15.26.2的其它地方并没有提到justjavac说的第二个限制,怪哉。

ECMA-334如是说:
ECMA-334, 4th Edition 写道
14.14.2 Compound assignment

An operation of the form x op= y is processed by applying binary operator overload resolution (§14.2.4) as if the operation was written x op y. Then,  
  • If the return type of the selected operator is implicitly convertible to the type of x, the operation is evaluated as x = x op y, except that x is evaluated only once.
  • Otherwise, if the selected operator is a predefined operator, if the return type of the selected operator is explicitly convertible to the type of x, and if y is implicitly convertible to the type of x or the operator is a shift operator, then the operation is evaluated as x = (T)(x op y), where T is the type of x, except that x is evaluated only once.
  • Otherwise, the compound assignment is invalid, and a compile-time error occurs.
The term “evaluated only once” means that in the evaluation of x op y, the results of any constituent expressions of x are temporarily saved and then reused when performing the assignment to x. [Example: In the assignment A()[B()] += C(), where A is a method returning int[], and B and C are methods returning int, the methods are invoked only once, in the order A, B, C. end example]
When the left operand of a compound assignment is a property access or indexer access, the property or indexer shall have both a get accessor and a set accessor. If this is not the case, a compile-time error occurs.
The second rule above permits x op= y to be evaluated as x = (T)(x op y) in certain contexts. The rule exists such that the predefined operators can be used as compound operators when the left operand is of type sbyte, byte, short, ushort, or char. Even when both arguments are of one of those types, the predefined operators produce a result of type int, as described in §14.2.6.2. Thus, without a cast it would not be possible to assign the result to the left operand.
The intuitive effect of the rule for predefined operators is simply that x op= y is permitted if both of x op y and x = y are permitted. [Example: In the following code
byte b = 0;
char ch = '\0';
int i = 0;
b += 1;    // Ok
b += 1000;      // Error, b = 1000 not permitted
b += i;        // Error, b = i not permitted
b += (byte)i;    // Ok
ch += 1;       // Error, ch = 1 not permitted
ch += (char)1;   // Ok

the intuitive reason for each error is that a corresponding simple assignment would also have been an error. end example]
[Note: Compound assignment operations support lifted operators. Since a compound assignment x op= y is evaluated as either x = x op y or x = (T)(x op y), the rules of evaluation implicitly cover lifted operators. end note]

14.14.3 Event assignment

If the left operand of a += or -= operator is an event, the expression is classified as an event access, and is evaluated as follows:
  • The instance expression, if any, of the event access is evaluated.
  • The right operand of the += or -= operator is evaluated, and, if required, converted to the type of the left operand through an implicit conversion (§13.1).
  • An event accessor of the event is invoked, with argument list consisting of the value computed in the previous step. If the operator was +=, the add accessor is invoked; if the operator was -=, the remove accessor is invoked.
An event assignment expression does not yield a value. Thus, an event assignment expression is valid only in the context of a statement-expression (§15.6).

C#中复合赋值运算符比Java规定了更多的转换相关规则,不过还是可以很直观的理解:(注意上面用蓝色色高亮的那句)只有当x op y和x = y都是合法的时候,x op= y才是合法的

也正是因为这样,所以justjavac提到的Java的两个陷阱在C#里都不存在:
1、编译错误:
static class Program {
    static void Main(string[] args) {
        byte b = 0;
        int i = 1;
        b += i; // error CS0266: 无法将类型“int”隐式转换为“byte”。存在一个显式转换(是否缺少强制转换?)
    }
}

不用像Java那样等到运行的时候再发现数据被剪了。

2、编译没问题,运行也没问题:
using System;
using System.Linq.Expressions;

static class Program {
    static void Main(string[] args) {
        string s = "str: ";
        object obj = (Expression<Func<int, int>>) (x => x + 1);
        s += obj;
        obj += s;
        Console.WriteLine(s);   // str: x => (x + 1)
        Console.WriteLine(obj); // x => (x + 1)str: x => (x + 1)
    }
}


==================

从OpenJDK的邮件列表里挖个东西顺带放这儿:
引用
Changeset: f09d6a3521b1
Author:    jjg
Date:      2008-03-06 10:07 -0800
URL:       http://hg.openjdk.java.net/jdk7/hotspot-comp/langtools/rev/f09d6a3521b1

4741726: allow Object += String
Summary: remove code in line with restriction removed from JLS
Reviewed-by: mcimadamore
Contributed-by: michaelbailey0 at gmail.com

! src/share/classes/com/sun/tools/javac/comp/Attr.java
+ test/tools/javac/StringConversion2.java
- test/tools/javac/expression/ObjectAppend.java
分享到:
评论

相关推荐

    C# for CSDN 乱七八糟的看不懂

    x++) { sum+=x; } 有条件循环 private void button1_Click(object sender, System.EventArgs e) { int sum=0; int x=0; while ((sum) & (x)) { x++; sum+=x; } string s2=Convert.ToString(x); MessageBox.Show(s2);...

    在一小时内学会 C#(txt版本)

    有两种数据类型: 1. 基本/内建类型 2. 用户定义类型 以下是 C# 内建类型的列表: 类型 字节 描述 byte 1 unsigned byte sbyte 1 signed byte short 2 signed short ushort 2 unsigned short int 4 signed ...

    《C#经典编程220例》.(明日科技).【带书签】-共3部分

    因上传大小限制,分三卷压缩,分别是:《C#经典编程220例》.(明日科技).【带书签】.zip、《C#经典编程220例》.(明日科技).【带书签】.z01、《C#经典编程220例》.(明日科技).【带书签】.z02 第1章 c#语言及其开发...

    c# 加密和解密相关代码

    str += md5data[i].ToString("x").PadLeft(2, '0'); //对遍历到的字节进行加密 } return str; //返回得到的加密字符串 } private void button1_Click(object sender, EventArgs e) { string P_str_Code = textBox1....

    c#学习笔记.txt

    如前所述,我是一个狮子座男人,一度我认为学习Java会使我看起来与众不同,可是几个月以后我放弃了这个选择,我看了论坛里关于这两种语言孰优孰劣的讨论,最终选择了C#,请不要问我为何做出这样的选择,很多人认为...

    VB课程设计俄罗斯方块

    俄罗斯方块的旋转主要将方块的位置加以变换得到的,例如上述范例,长条型有两中样式,根据小方块的编号变动来实现整个造型的旋转,比如: If n(0) - 18 &gt;= 2 And n(3) + 9 &lt;= 198 Then If cmdfang(n(0) - 18)....

    C++程序设计基础实例教程

    C++ 第一章 C++基础知识 1.1 程序设计基本概念 1. 程序=算法+数据结构 2. 算法:解决问题所列出来的步骤 ...例2:从键盘上输入两个数,求这两个数的和。 程序如下: #include "iostream.h" int addxy(int a, int b)

    疯狂JAVA讲义

    1.2.1 C#简介和优势 4 1.2.2 Ruby简介和优势 4 1.2.3 Python的简介和优势 5 1.3 Java程序运行机制 5 1.3.1 高级语言的运行机制 6 1.3.2 Java程序的运行机制和JVM 6 1.4 开发Java的准备 7 1.4.1 安装JDK 8 ...

Global site tag (gtag.js) - Google Analytics