`
RednaxelaFX
  • 浏览: 3052808 次
  • 性别: 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#重载运算符详解

    以题目中的`EmployeeDetail`类为例,我们可以为这个类重载`+`运算符,使得两个`EmployeeDetail`对象相加时,创建一个新的`EmployeeCollection`对象,包含这两个员工的信息。这可以通过定义如下两个重载方法实现: `...

    简单的C#事件使用DEMO(详细的注释+简单易懂的例子)

    在订阅者类中,我们需要定义一个符合事件处理程序签名的方法,并使用`+=`运算符将其添加到事件中。当事件触发时,这个方法会被调用。 ```csharp public void OnMyEvent(object sender, EventArgs e) { // 处理...

    C# 类间通信实例(事件机制)

    然后,订阅者可以使用`+=`运算符连接到事件源的事件: ```csharp eventSource.MyEvent += OnMyEvent; ``` 触发事件时,只需调用事件委托即可: ```csharp MyEvent?.Invoke(this, new MyEventArgs(...)); ``` 在...

    浅析C#中object sender与EventArgs e

    3. 最后,通过`+=`运算符将事件处理方法绑定到事件上,如`this.button1.Click += new System.EventHandler(this.button1_Click);`。 事件处理的工作流程是这样的:当事件触发时(例如用户点击按钮),系统会调用...

    C#项目经典实战案例1200例(PDF)

    这套资源分为两卷,共计1200个实例,旨在帮助开发者深入理解和掌握C#的核心概念以及在项目开发中的实际应用技巧。 C#是一种由微软公司开发的面向对象的编程语言,它被广泛应用于Windows平台的软件开发、游戏开发、...

    C#基础知识.doc

    )等,还有赋值运算符(=、+=、-=、*=、/=、%=)。 4. **运算符优先级**:运算符的优先级决定了表达式的计算顺序,例如括号()具有最高优先级,然后是乘除(*)、加减(+),最后是赋值(=)。 5. **数据类型转换**:C#...

    C#实用编程百例(续1)

    通过`+=`运算符,我们订阅了事件,并提供了一个匿名方法作为事件处理程序。 "C#实用编程百例(续1)"可能还会涵盖更多主题,如异常处理、多线程、文件I/O、网络编程、数据库访问等。每一道实例都将帮助你加深对C#...

    事件与委托

    创建委托实例之后,可以通过`+=`运算符将方法绑定到委托上: ```csharp MyDelegate myDelegate = new MyDelegate(MyMethod); myDelegate += MyAnotherMethod; myDelegate("Hello, Delegate!"); ``` 这里`MyMethod...

    Visual C#.NET 应用编程150例.rar

    学习C#.NET首先要掌握C#的基本语法,包括变量、数据类型、运算符、控制结构(如if语句、for循环、while循环)、函数、类和对象等。 2. **.NET Framework**:它是微软开发的软件框架,提供了丰富的类库和运行时环境...

    C#开发实战1200例(第1卷)源码

    《C#开发实战1200例(第1卷)源码》是一个全面涵盖C#编程实践的资源集合,提供了1200个实例代码,旨在帮助开发者深入理解和掌握C#语言的核心特性和实际应用。这个资源包包含了两个RAR压缩文件,即MR12-25.rar和MR1-11....

    C#开发实战1200例(第2卷)源码

    《C#开发实战1200例(第2卷)源码》是针对C#编程语言的一本实战性教程,其核心在于通过大量的实例来帮助读者深入理解和掌握C#编程技术。这本书的第二卷源码提供了丰富的代码示例,覆盖了C#语言的各个方面,包括基础...

    C#开发实战1200例-第2卷-王小科.王军 .rar

    1. **基础语法**:C#的基础包括变量、数据类型、运算符、流程控制(如if语句、for循环、while循环)、函数、类与对象等。这些是所有编程语言的基础,也是初学者的入门点。 2. **面向对象编程**:C#作为一门面向对象...

    c#中new-的几种用法-经典案例-公司应聘 c#经典案例.doc

    在 C# 中,new 运算符和 new 修饰符是两个不同的概念。new 运算符用于创建对象和调用构造函数,而 new 修饰符用于隐藏基类成员的继承成员。了解这两个概念的用法和应用场景对于编写高效、灵活的 C# 代码非常重要。 ...

    C#实例程序100例

    1. **C#基础语法**:C#是一种强类型、面向对象的语言,学习之初会接触到变量声明、数据类型(如int, string, bool等)、运算符、控制流(if-else, switch, for, while等)以及函数的使用。 2. **类与对象**:C#是...

    第3章 C#程序设计基础(C#_程序设计与开发PPT课件).ppt

    - 常见的运算符还包括算术运算符(加减乘除等)、赋值运算符(`=`, `+=`, `-=`等)、关系运算符(`==`, `!=`, `, `&gt;`等)和逻辑运算符(`&&`, `||`, `!`等)。 5. **案例分析** - 例3-1展示了不同数值类型的赋值...

    C#实用编程百例

    《C#实用编程百例》是一本专注于C#编程实践的书籍,其光盘源码包含了大量的实例,旨在帮助读者深入理解和掌握C#语言的核心概念和技术。这些实例覆盖了C#编程的各个方面,从基础语法到高级特性,是学习和提升C#编程...

    Visual C#.NET编程精粹150例

    1. **C#基础**:书中首先会介绍C#的基础语法,包括变量、数据类型、运算符、控制流(如if语句、switch语句、循环)、函数、类与对象等。这些是学习任何面向对象语言的基石,掌握它们能让你更好地理解C#程序的构造。 ...

    C#中的 == 和equals()区别浅析

    在C#编程语言中,`==`运算符和`Equals()`方法是用来比较对象或值类型是否相等的两种常见方式,但它们之间存在着显著的区别。本文将深入探讨这两种比较方式的工作原理及其应用场景。 首先,`==`运算符是C#中的一个...

    勾月计算器程序(C#源代码编写)现在实现了加、减、乘、除功能。内含有swithc,case,break等用法,算法简单,是C#初学者的一个很好例子

    本文将以“勾月计算器程序”为例,深入解析C#语言中的基本运算逻辑、switch-case-break语句的运用以及程序设计的思路。 首先,让我们关注这个程序的核心功能——加、减、乘、除运算。在C#中,这些基本的算术运算...

    C#编程四则计算器-界面

    C#是一种面向对象的编程语言,广泛应用于Windows应用开发,尤其是在构建桌面应用程序时,如本例中的计算器。 四则运算,即加法、减法、乘法和除法,是基础数学中的基本运算。在C#中实现这些运算通常涉及使用算术...

Global site tag (gtag.js) - Google Analytics