2.3 运算符和表达式
C#提供了许多处理变量的运算符,表达式是由操作数和运算符组合而成,表达式中的操作数可以是变量、常量或者子表达式,它是计算的基本构件。
2.3.1 运算符的分类
1.按操作数划分
运算符按操作数来分,大致可以分为如下三类。
(1)一元运算符:处理一个操作数。
(2)二元运算符:处理两个操作数。
(3)三元运算符:处理三个操作数。
2.按类型划分
按类型来划分,可以分为算术运算符、赋值运算符、关系运算符、逻辑运算符等。
1)算术运算符
算术运算符包括一元运算符++、--,以及二元运算符+、-、*、/、%,如图2-4所示。其中,一元运算符又称为单目运算符。
图2-4 算术运算符分类
表2-2列出了这些运算符,并使用简单的示例介绍了它们的用法。
表2-2 算术运算符
表2-2中的运算符+在用于字符串类型的操作数时,其结果的含义为:两操作数的字符串的拼接值。++运算符和--运算符可位于操作数的前面,也可位于操作数的后面,位于操作数前面表示操作数先进行自增(自减)再参与运算,位于操作数后面表示操作数先参与运算再进行自增(自减)。
下面通过一个小实例来练习算术运算符的使用。
例2-2:算术运算符的使用(ConsoleArithmeticOperators)
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleArithmeticOperators { class Program { static void Main(string[] args) { double num1, num2; Console.WriteLine("请输入两个数字。"); Console.Write("第一个数字为:"); num1 = Convert.ToDouble(Console.ReadLine()); Console.Write("第二个数字为:"); num2 = Convert.ToDouble(Console.ReadLine()); Console.WriteLine("第一个数{0}与第二个数{1}之和为{2}", num1, num2, num1 + num2); Console.WriteLine("第一个数{0}与第二个数{1}之差为{2}", num1, num2, num1 - num2); Console.WriteLine("第一个数{0}与第二个数{1}之积为{2}", num1, num2, num1 * num2); Console.WriteLine("第一个数{0}与第二个数{1}之商为{2}", num1, num2, num1 / num2); Console.WriteLine("第一个数{0}与第二个数{1}取余为{2}", num1, num2, num1 % num2); Console.WriteLine("第一个数{0}后自增的结果为{1}", num1, num1++); Console.WriteLine("第二个数{0}先自增的结果为{1}", num2, ++num2); Console.WriteLine("当前第一个数的值为{0}", num1); Console.WriteLine("当前第二个数的值为{0}", num2); Console.WriteLine("第一个数{0}后自减的结果为{1}", num1, num1--); Console.WriteLine("第二个数{0}先自减的结果为{1}", num2, --num2); Console.WriteLine("当前第一个数的值为{0}", num1); Console.WriteLine("当前第二个数的值为{0}", num2); Console.ReadLine(); } } }
运行结果如图2-5所示。
图2-5 算术运算符的使用
关键点解析:
Console.WriteLine("第一个数{0}后自增的结果为{1}", num1, num1++);
此句使用了一元运算符++,num1++因为是后自增,即num1先参与运算,再自增1,所以此句输出:第一个数7后自增的结果为7。
Console.WriteLine("第二个数{0}先自增的结果为{1}", num2, ++num2);
此句同上也使用了一元运算符++,++num2因为是先自增,即num2先自增1再参与运算,所以此句输出:第二个数3先自增的结果为4。
Console.WriteLine("当前第一个数的值为{0}", num1); Console.WriteLine("当前第二个数的值为{0}", num2);
此时,num1与num2的值较最初都已经自增了1,所以此时num1与num2的值分别为8和4。
Console.WriteLine("第一个数{0}后自减的结果为{1}", num1, num1--);
此句使用了一元运算符--,num1--因为是后自减,即num1先参与运算,再自减1,所以此句输出:第一个数8后自减的结果为8。
Console.WriteLine("第二个数{0}先自减的结果为{1}", num2, --num2);
此句使用了一元运算符--,--num2因为是先自减,即num2先自减1再参与运算,所以此句输出:第二个数4先自减的结果为3。
Console.WriteLine("当前第一个数的值为{0}", num1); Console.WriteLine("当前第二个数的值为{0}", num2);
此时,num1与num2的值都已经自减1完成,所以此时num1与num2的值分别为7和3。
2)赋值运算符
除了一直在使用的=赋值运算符外,还有其他赋值运算符,如表2-3所示,它们都是根据运算符和右操作数,把一个值赋给左边的变量。
表2-3 赋值运算符
+=运算符也可用于字符串类型的操作数,与+运算符相同。
3)关系运算符
关系运算符用于测试两个操作数或两个表达式之间的关系,其中操作数可以是变量、常量或表达式。关系运算符的计算结果为bool值。关系运算符包括以下6种,如表2-4所示。
表2-4 关系运算符
4)逻辑运算符
逻辑运算符用于连接一个或多个条件,判断这些条件是否成立。逻辑运算符的类型如表2-5所示。
表2-5 逻辑运算符
其中,&和&&、|和||运算符的结果完全相同,但两者的区别是:如果&&运算符的第一个操作数为false,就不需要判断第二个操作数的值了,因为无论第二个操作数的结果是什么,其结果都是false。同样,如果第一个操作数是true,则||运算符返回true,则不需要判断第二个操作数的值了。但&和|运算符无论第一个操作数结果是什么,却总要计算第二个操作数,这样就带来了程序性能上的损耗,所以应尽量使用&&和||运算符来代替&和|运算符。
2.3.2 运算符的优先级
当计算表达式时,会按顺序处理每个运算符,但这并不意味着必须从左右至右地运用这些运算符,需要确定先执行哪种运算,此时就需要考虑运算符的优先级。
例如,表达式p=x-y+z*n*(m/q)+28-t%3-6;应先算哪部分?要解决诸如此类的问题就要使用运算符的优先级了。
表2-6列出了各运算符的优先级。
表2-6 运算符的优先级