一、概念介绍
操作数
含义:操作数是指作为参与运算的元素。
可作为操作数的结构:
字面量
常量
变量
方法调用
元素访问器(如数组访问器和索引器)
其他表达式
运算符
含义:运算符是一个符号,表示返回单个结果的操作。
运算符作用:
将操作数作为输入
执行某个操作
基于该操作返回一个值
运算符优先级:
结合性:
当连续的运算符有相同的优先级别时,求值顺序由结合性来决定。
左结合运算符从左至右求值
右结合运算符从右至左求值
除了赋值运算符外,其他二元运算符都是左结合的
赋值运算符和条件运算符是右结合的
设定优先级:
可以使用一对圆括号设定子表达式的求值顺序。(有括号先算括号里的)
覆盖结合性和优先级规则
求值顺序从嵌套的最内层到最外层
表达式
含义:表达式是一组运算符和操作数的字符串
表达式求值:将每个操作数以特定顺序经运算符计算的过程
字面量
字面量介绍
含义:字面量是指源代码中键入的数字或字符串,表示一个指定类型的、明确的、固定的值。
因为字面量是写进源代码的,所以它们的值必须在编译时可知。
预定义类型有自己的字面量形式。
对于引用类型,字面量null表示变量没有设置为内存中的数据。
字面量示例:
整数字面量
含义:整数字面量没有小数点,带有可选的后缀指明整数的类型。
整数字面量可以是十进制或十六进制,十六进制必须以0x或0X开头。
如果没有后缀,编译器会把字符串解释为能解释该值而不丢失数据的相应类型最小的类型。
示例:
实数字面量
实数字面量组成如下:
十进制数字
一个可选的小数点
一个可选的指数部分
一个可选的后缀
示例:
实数字面量的后缀:
字符字面量
字符字面量由两个单引号内的字符组成。其组成可以是下面任意一种:
单个字符
一个简单的转义序列(一个反斜杠后面跟着单个字符)
一个十六进制转义序列(一个反斜杠后面跟着一个大写或小写的x,后面再跟4个十六进制数字)
一个Unicode转义序列(一个反斜杠后面跟着一个大写或小写的u,后面再跟4个十六进制数字)
示例:
重要的特殊字符:
字符串字面量
含义:字符串字面量使用双引号标记。相同的字符串字面量共享堆中同一内存位置以节约内存。有两种字符串字面量类型,如下:
常规字符串字面量
逐字字符串字面量
常规字符串字面量包含:
字符
简单转义序列
十六进制和Unicode转义序列
逐字字面量的书写如同常规字面量,但它以一个@字符作为前缀,具有以下特征:
逐字字面量和常规字面量的唯一区别是会忽略转义字符
逐字字面量中两个相邻的双引号被解释为单个双引号
代码示例:
二、运算符重载
含义:C#运算符被定义为使用预定义类型作为操作数来工作。面对一个用户定义类型,运算符完全不知道如何处理它。运算符重载允许你定义C#运算符应该如何操作自定义类型。重载运算符应该符合运算符的直观含义。
要求:
运算符重载只能用作类和结构。
为类和运算符重载一个运算符x,可以声明一个名称为operator x的方法并实现它的行为。
一元运算符的重载方法带一个单独的class或struct类型的参数。
二元运算符的重载方法带两个参数,其中一个必须是class或struct类型的参数。
声明必须同时使用public static修饰。
运算符必须是要操作的类或结构的成员。
运算符重载的限制
可重载的运算符有类型限制
运算符重载不能做下面的事情:
创建新运算符
改变运算符的语法
重新定义运算符如何处理预定义类型
改变运算符的优先级或结合性
代码示例:
class LimitedInt
{
const int MaxValue = 100;
const int MinValue = 0;
private int _theValue = 0;
public int TheValue //TheValue属性,限制私有字段_theValue的最大值和最小值
{
get { return _theValue; }
set
{
if (value < MinValue)
_theValue = 0;
else
_theValue = value > MaxValue?MaxValue:value;
}
}
//运算符重载,负数。将负数运算符自定义为:若去一个值为负数,将其赋值为0
public static LimitedInt operator - (LimitedInt x)
{
LimitedInt li = new LimitedInt();
li.TheValue = 0;
return li;
}
//运算符重载,减法。两个本类型相减,计算其成员TheValue相减,计算结果放在一个新的本类型对象中
public static LimitedInt operator -(LimitedInt x, LimitedInt y)
{
LimitedInt li = new LimitedInt();
li.TheValue = x.TheValue - y.TheValue;
return li;
}
//运算符重载,加法。一个本类型和一个double类型相加,结果保存到新的本类型对象中
public static LimitedInt operator +(LimitedInt x,double y)
{
LimitedInt li = new LimitedInt();
li.TheValue = x.TheValue + (int)y;
return li;
}
}
class Program
{
static void Main(string[] args)
{
LimitedInt li1 = new LimitedInt();
LimitedInt li2 = new LimitedInt();
LimitedInt li3 = new LimitedInt();
li1.TheValue = 11;
li2.TheValue = 66;
Console.WriteLine("li1 = {0},li2 = {1}",li1.TheValue,li2.TheValue);
//使用重载的负数运算符
li3 = -li1;
Console.WriteLine("li3 = {0},li1 = {1}", li3.TheValue, li1.TheValue);
//使用重载的减法运算符
li3 = li2 - li1;
Console.WriteLine("li3:{0} 等于 li2:{1} 减去 li1:{2}",li3.TheValue,li2.TheValue,li1.TheValue);
li3 = li1 - li2;
Console.WriteLine("li3:{0} 等于 li1:{1} 减去 li2:{2}", li3.TheValue, li1.TheValue, li2.TheValue);
三、typeof运算符
含义:对任何已知类型,只有一个System.Type对象。typeof运算符返回作为其参数的任何类型的System.Type对象。
typeof运算符是一元运算符
typeof运算符不能被重载
语法示例:
Type t = typeof(SomeClass);
代码示例:
using System.Reflection;//使用反射命名空间来全面利用检测类型信息的功能
class SomeClass
{
public int Field1;
public int Field2;
public void Method1() { }
public int Method2(){ return 1;}
}
class Test
{
static void Main(string[] args)
{
Type t = typeof(SomeClass);
FieldInfo[] fi = t.GetFields();
MethodInfo[] mi = t.GetMethods();
foreach (FieldInfo element in fi)
Console.WriteLine("Field:{0}",element.Name);
foreach (MethodInfo element in mi)
Console.WriteLine("Method:{0}",element.Name);
}
}
(本章内容学习总结自《C#图解教程》)