C# 操作符
C# 语言中有大量的操作符,这些操作符是指定在表达式中执行操作的符号,C# 中预定义了算术操作符、逻辑操作符及其它的操作符,有些可以重载,在应用到自定义类型时其意义可以改变。
操作符分类表
操作符类型 操作符
算术 + - * / %
逻辑(布尔型和按位) & | ^ ! ~ && || true false
字符串连接 +
递增、递减 ++ --
移位 << >>
关系 == != < > <= >=
赋值 = += -= *= /= %= &= |= ^=
逻辑(布尔型和按位)
字符串连接
递增、递减
移位
关系
赋值
<<= >>= ??
成员访问 .
索引 []
转换 ()
条件 ?:
委托连接和删除 + -
对象创建 new
类型信息 as is sizeof typeof
溢出异常控制 checked unchecked
间接寻址和地址 * -> [] &
成员访问
索引
转换
条件
委托连接和删除
对象创建
类型信息
溢出异常控制
间接寻址和地址
1. 算术溢出
使用算术运算符(+、-、*、/)可能会产生超出调用的数值类型可以存放的数值范围。通常有以下几种情况:
· 整数算术溢出或者产生 OverflowException 异常,或者丢弃结果的最高有效位。整数被零除将引发 DivideByZeroException 异常。
· 浮点算术溢出或被零除从不引发异常,因为浮点类型基于IEEE 754,因此可以表示无穷和 NaN(非数字)。
· decimal 算术溢出总是引发 OverflowException 异常,decimal 被零除总是引发 DivideByZeroException 异常。
· 浮点算术溢出或被零除从不引发异常,因为浮点类型基于IEEE 754,因此可以表示无穷和 NaN(非数字)。
· decimal 算术溢出总是引发 OverflowException 异常,decimal 被零除总是引发 DivideByZeroException 异常。
当发生整数溢出时,产生的结果取决于执行环境,执行环境可为 checked 或 unchecked。在 checked 环境下,将产生 OverflowException 异常。在 unchecked 环境下,将放弃结果的最高有效位并继续执行。因此,C# 使您有机会选择处理或忽略溢出。
除算术运算符以外,整型之间的强制转换也会导致溢出(例如,将 long 强制转换为 int),溢出的结果也取决于 checked 或 unchecked 的执行环境。然而,按位运算符和移位运算符不会产生溢出。
2. [] 操作符
方括号([])用于数组、索引器和属性,也可用于指针。
数组类型是在类型的后面加上 []。例如:
int [] myarray; //myarray是一个整数数组。
myarray = new int[100]; //创建100个元素的整数数组。
myarray = new int[100];
若要访问数组中的元素,将元素的索引放到方括号中。例如:
myarray[0] = myarray[1] = 1;
for (int i=2; i<100; ++i) myarray[i] = myarray[i-1] + myarray[i-2];
myarray[0] = myarray[1] = 1;
for (int i=2; i<100; ++i) myarray[i] = myarray[i-1] + myarray[i-2];
如果数组索引超出范围,将会产生异常。
不能重载数组索引运算符;但类型可以定义采用一个或多个参数的索引器和属性。索引器参数括在方括号中(就像数组索引一样),但索引器参数可声明为任何类型(这与数组索引不同,数组索引必须为整数)。
例如,.NET Framework 中定义了一个 Hashtable 类型,它的键可以和任意类型的数值关联。
Collections.Hashtable h = new Collections.Hashtable();
h["a"] = 123; // 使用字符串作为索引
h["a"] = 123;
方括号还用于指定属性:
[attribute (AllowMultiple=true)]
public class Attr
{
}
public class Attr
{
}
可以使用方括号来指定指针索引:
unsafe fixed ( int* p = myarray ) // p指向前面例子中的myarray
{
p[0] = p[1] = 1;
for( int i=2; i<100; ++i ) p[i] = p[i-1] + p[i-2];
}
unsafe fixed ( int* p = myarray )
{
}
不执行边界检查。
3. () 操作符
圆括号除了用于指定表达式中的运算顺序外,还用于指定强制转换或类型转换。
语法:
(type) expr
语法:
(type) expr
其中:
type 表示expr转换后类型的名称。
expr 表示一个表达式。
type 表示expr转换后类型的名称。
expr 表示一个表达式。
类型转换会显示调用实现expr的类型到type类型的转换操作符,如果未定义这样的操作符,转换就会失败。
不能重载 () 运算符。
4. . 操作符
点运算符(.)用于成员访问。点运算符指定类型或命名空间的成员。
例如下面的类:
例如下面的类:
class Exam
{
public int x;
public int y;
{
}
}
Exam s = new Exam();
{
}
Exam s = new Exam();
变量Exam包含x和y两个成员,要访问它们,就需要使用点操作符。
s.x = 6; // 给赋a赋值
s.y = 9; // 给域b赋值
s.y = 9;
点还用于构造限定名,即指定其所属的命名空间或接口的名称。
System.Console.WriteLine("hello"); // 类 Console 在名称空间 System 中
using 指令使某些名称限定变成可选:
using System;
// ...
System.Console.WriteLine("hello");
Console.WriteLine("hello"); // 结果同上
using 指令使某些名称限定变成可选:
using System;
// ...
System.Console.WriteLine("hello");
Console.WriteLine("hello");
但是当某一标识符不确定时,必须限定它:
using System;
using OtherSystem; // 另一个也包含 Console 类的名称空间
// ...
System.Console.WriteLine( "hello" ); // 必须限定 Console类
// ...
System.Console.WriteLine( "hello" );
5. + 操作符
+ 操作符既可作为一元操作符也可作为二元操作符。
一元 + 操作符是为所有数值类型预定义的。对数值类型进行一元 + 运算的结果就是操作数的值。
为数值类型和字符串类型预定义了二元 + 操作符。对于数值类型,+ 计算两个操作数之和。当其中的一个或两个操作数是字符串类型时,+ 将操作数的字符串表示形式串联在一起。
委托类型也提供二元 + 操作符,它执行委托连接。
用户定义的类型可以重载一元 + 和二元 + 操作符。在枚举时通常允许整型运算。
示例:
// cs_operator_plus.cs
using System;
class MainClass
{
static void Main()
{
Console.WriteLine(+5); // 一元 +
Console.WriteLine(5 + 5); // 加法
Console.WriteLine(5 + .5); // 加法
Console.WriteLine("5" + "5"); // 字符串连接
Console.WriteLine(5.0 + "5"); // 字符串连接
// 注意:自动由double类型转换为string类型
}
}
// cs_operator_plus.cs
using System;
class MainClass
{
}
输出:
5
10
5.5
55
55
10
5.5
55
55
6. - 操作符
- 操作符既可作为一元操作符也可作为二元操作符。
一元 - 操作符是为所有数值类型预定义的。数值类型的一元 - 运算的结果是操作数的相反数。
二元 - 运算符是为所有数值类型和枚举类型预定义的,用于从第一个操作数中减去第二个操作数。
委托类型也提供了二元 - 操作符,它执行委托删除操作。
用户定义的类型可以重载一元 - 和二元 - 操作符。
示例:
// cs_operator_minus.cs
using System;
class MainClass
{
static void Main()
{
int a = 5;
Console.WriteLine(-a);
Console.WriteLine(a - 1);
Console.WriteLine(a - .5);
}
}
using System;
class MainClass
{
}
输出:
-5
4
4.5
4
4.5
7. * 操作符
乘法操作符(*)用于计算两个操作数的积。另外还用作取消引用操作符,允许读取和写入指针。
所有数值类型都具有预定义的乘法操作符。
* 操作符还用来声明指针类型和取消引用指针。该运算符只能在不安全的环境中使用,通过 unsafe 关键字的使用来表示,并且需要 /unsafe 编译器选项。取消引用操作符也称为间接寻址操作符。
用户定义的类型可重载 * 操作符。重载二元 * 操作符时,也会隐式重载相应的赋值操作符(如果有)。
示例:
// cs_operator_mult.cs
using System;
class MainClass
{
static void Main()
{
Console.WriteLine(5 * 2);
Console.WriteLine(-.5 * .2);
Console.WriteLine(-.5m * .2m); // decimal type
}
}
// cs_operator_mult.cs
using System;
class MainClass
{
}
输出:
10
-0.1
-0.10
10
-0.1
-0.10
示例:
// cs_operator_ptr.cs
// 需要 /unsafe 编译选项
public class MainClass
{
unsafe static void Main()
{
int i = 5;
int* j = &i;
System.Console.WriteLine(*j);
}
}
// 需要 /unsafe 编译选项
public class MainClass
{
}
输出:
5
5
8. / 操作符
除法操作符(/)用第二个操作数除第一个操作数。所有数值类型都具有预定义的除法操作符。
用户自定义的类型可重载 / 操作符。重载 / 操作符将隐式重载 /=操作符。
示例:
// cs_operator_division.cs
using System;
class MainClass
{
static void Main()
{
Console.WriteLine(-5/2);
Console.WriteLine(-5.0/2);
}
}
using System;
class MainClass
{
}
输出:
-2
-2.5
-2.5