VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > temp > C#教程 >
  • c#的+=运算符两则

制作者:剑锋冷月 单位:无忧统计网,www.51stat.net
 

  刚偶尔看到了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 = '';
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)        }    } 

 

 

  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 = '';
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

 



相关教程