程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> 關於C# >> C#的+=運算符兩例

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

C#代碼

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、編譯錯誤:

C#代碼

static class Program {
    static void Main(string[] args) {
        byte b = 0;
        int i = 1;
        b += i; // error CS0266: 無法將類型“int”隱式轉換為“byte”。存在一個顯式轉換(是否缺少強制轉換?)
    }
}

不用像Java那樣等到運行的時候再發現數據被剪了。

2、編譯沒問題,運行也沒問題:

C#代碼

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
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved