4.2 运算符

运算符是一些特殊的符号,主要用于数学函数、一些类型的赋值语句和逻辑比较方面。C#中提供了丰富的运算符,如算术运算符、赋值运算符、比较运算符等。本节将向读者介绍这些运算符。

4.2.1 算术运算符

视频讲解:光盘\TM\lx\4\02算术运算符.mp4

+、-、*、/和%运算符都称为算术运算符,分别用于进行加、减、乘、除和模(求余数)运算。C#中算术运算符的功能及使用方式如表4.1所示。

表4.1 C#算术运算符

其中,“+”和“-”运算符还可以作为数据的正负符号,如+5、-7。

1.加法运算符

加法运算符(+)通过两个数相加来执行标准的加法运算。

【例4.2】创建一个控制台应用程序,声明两个整型变量M1和M2,并将M1赋值为927,然后使M2的值为M1与M1相加之后的值,代码如下。(实例位置:光盘\TM\sl\4\2)

        static void Main(string[] args)
        {
            int M1=927;                                   //声明整型变量M1,并赋值为927
            int M2;                                       //声明整型变量M2
            M2=M1+M1;                                     //M2的值为M1与M1相加之后的值
            Console.WriteLine(M2.ToString());
            Console.Read();
        }

程序的运行结果为1854。

说明 如果想要对整型变量M进行加1操作,可以用“M=M+1; ”来实现,也可以用增量运算符(++)实现,如M++或++M。++M是前缀增量操作,该操作的结果是操作数加1之后的值;M++是后缀增量操作,该运算的结果是操作数增加之前的值。

2.减法运算符

减法运算符(-)通过从一个表达式中减去另外一个表达式的值来执行标准的减法运算。

【例4.3】创建一个控制台应用程序,声明两个decimal类型变量R1和R2,并分别赋值为1112.82和9270.81,然后再声明一个decimal类型变量R3,使其值为R2减去R1之后得到的值,代码如下。(实例位置:光盘\TM\sl\4\3)

        static void Main(string[] args)
        {
            decimal R1=(decimal)1112.82;                     //声明整型变量R1,并赋值为1112.82
            decimal R2=(decimal)9270.81;                     //声明整型变量R2,并赋值为9270.81
            decimal R3;                                      //声明整型变量R3
            R3=R2-R1;                                        //R3的值为R2减去R1得到的值
            Console.WriteLine(R3.ToString());
            Console.Read();
        }

程序的运行结果为8157.99。

说明 如果想要对整型变量R进行减1操作,可以用“M=M-1; ”来实现,也可以用减量运算符(--)实现,如R--或--R。--R是前缀减量操作,该操作的结果是操作数减1之后的值;R--是后缀减量操作,该运算的结果是操作数减少之前的值。

3.乘法运算符

乘法运算符(*)将两个表达式进行乘法运算并返回它们的乘积。

【例4.4】创建一个控制台应用程序,声明两个整型变量ls1和ls2,并分别赋值为10和20。再声明一个整型变量sum,使其值为ls1和ls2的乘积,代码如下。(实例位置:光盘\TM\sl\4\4)

        static void Main(string[] args)
        {
            int ls1=10;                                    //声明整型变量ls1,并赋值为10
            int ls2=20;                                    //声明整型变量ls2,并赋值为20
            int sum;                                       //声明整型变量sum
            sum=Is1*Is2;                                   //使sum的值为ls1和ls2的乘积
            Console.WriteLine(sum.ToString());
            Console.Read();
        }

程序的运行结果为200。

4.除法运算符

除法运算符(/)执行算术除运算,它用被除数表达式除以除数表达式而得到商。

【例4.5】创建一个控制台应用程序,声明两个整型变量shj1和shj2,并分别赋值为45和5。再声明一个整型变量ls,使其值为shj1除以shj2得到的值,代码如下。(实例位置:光盘\TM\sl\4\5)

        static void Main(string[] args)
        {
            int shj1=45;                                   //声明整型变量shj1,并赋值为45
            int shj2=5;                                    //声明整型变量shj2,并赋值为5
            int ls;                                        //声明整型变量ls
            Is=shj1/shj2;                                  //使ls的值为shj1除以shj2得到的值
            Console.WriteLine(ls.ToString());
            Console.Read();
        }

程序的运行结果为9。

注意 在用算术运算符(+、-、*、/)运算时,产生的结果可能会超出所涉及数值类型的值的范围,这样,会导制运行结果不正确。

5.求余运算符

求余运算符(%)返回除数与被除数相除之后的余数,通常用这个运算符来创建余数在特定范围内的等式。

【例4.6】创建一个控制台应用程序,声明两个整型变量I1和I2,并分别赋值为55和10。再声明一个整型变量I3,使其值为I1与I2求余运算之后的值,代码如下。(实例位置:光盘\TM\sl\4\6)

        static void Main(string[] args)
        {
            int I1=55;                                     //声明整型变量I1,并赋值为55
            int I2=10;                                     //声明整型变量I1,并赋值为10
            int I3;                                        //声明整型变量I3
            I3=I1 % I2;                                    //使I3等于I1与I2求余运算之后的值
            Console.WriteLine(I3.ToString());
            Console.Read();
        }

程序的运行结果为5。

说明 在获取两个数相除的余数时,也可以用Math类的DivRem方法来实现,如上述代码中的I3 = I1 % I2可以写成Math.DivRem(I1, I2, out I3), I3中存储了I1和I2的余数。

闯关训练:根据第4.2.1节所学知识,制作一个简易的计算器程序,可以实现两个数的加、减、乘、除运算。

4.2.2 赋值运算符

视频讲解:光盘\TM\lx\4\03赋值运算符.mp4

赋值运算符为变量、属性、事件等元素赋新值。赋值运算符主要有=、+=、-=、*=、/=、%=、&=、|=、^=、<<=和>>=运算符。赋值运算符的左操作数必须是变量、属性访问、索引器访问或事件访问类型的表达式,如果赋值运算符两边的操作数的类型不一致,就需要首先进行类型转换,然后再赋值。

在使用赋值运算符时,右操作数表达式所属的类型必须可隐式转换为左操作数所属的类型,运算将右操作数的值赋给左操作数指定的变量、属性或索引器元素。C#中的赋值运算符及其运算规则如表4.2所示。

表4.2 赋值运算符

下面以加赋值(+=)运算符为例,举例说明赋值运算符的用法。

【例4.7】创建一个控制台应用程序,声明一个int类型的变量i,并初始化为927,然后通过加赋值运算符改变i的值,使其在原有的基础上增加112,代码如下。(实例位置:光盘\TM\sl\4\7)

        static void Main(string[] args)
        {
            int i=927;                                  //声明一个int类型的变量i并初始化为927
            i+=112;                                     //使用加赋值运算符
            Console.WriteLine("最后i的值为:{0}", i);     //输出最后变量i的值
            Console.ReadLine();
        }

程序的运行结果为:

最后i的值为:1039

说明 在C#中可以把赋值运算符连在一起使用。如:

x = y = z = 5;

在这个语句中,变量x、y、z都得到同样的值5,但在程序开发中不建议使用这种赋值语法。

互动练习:尝试使用C#制作一个张家口冬奥会的倒计时程序,具体要求为:使用当前日期和张家口冬奥会的开幕日期相比较,得出天数,然后以图片的形式显示倒计时天数。

4.2.3 关系运算符

视频讲解:光盘\TM\lx\4\04关系运算符.mp4

关系运算符属于二元运算符,用于程序中的变量之间、变量和自变量之间以及其他类型的信息之间的比较,它返回一个代表运算结果的布尔值。当运算符对应的关系成立时,运算结果为true,否则为false。所有关系运算符通常用在条件语句中来作为判断的依据。C#中的关系运算符共有6个,如表4.3所示。

关系运算符就好像对两个铁球进行比较,看看这两个铁球哪个大,重量是否相等,并给出一个“真”或“假”的值。

表4.3 关系运算符

下面对这几种关系运算符进行详细讲解。

1.相等运算符

要查看两个表达式是否相等,可以使用相等运算符(==)。相等运算符对整型、浮点型和枚举类型数据的操作是一样的。它只简单地比较两个表达式,并返回一个布尔结果。

【例4.8】创建一个控制台应用程序,声明两个decimal类型变量L1和L2,并分别赋值为1981.00m和1982.00m,然后再声明一个bool类型变量result,使其值等于L1和L2进行相等运算后的返回值,代码如下。(实例位置:光盘\TM\sl\4\8)

        decimal L1=1981.00m;                              //声明decimal类型变量L1
        decimal L2=1982.00m;                              //声明decimal类型变量L2
        bool result;                                      //声明bool类型变量result
        //使result等于L1和L2进行相等运算后的返回值
        resuIt = L1 == L2;
        Console.WriteLine(result);                        //输出运行结果
        Console.ReadLine();

程序的运行结果为false。

2.不等运算符

不等运算符(! =)是与相等运算符相反的运算符,有两种格式的不等运算符可以应用到表达式,一种是普通的不等运算符(! =),另外一种是相等运算符的否定!(a==b)。通常,这两种格式可以计算出相同的值。

【例4.9】创建一个控制台应用程序,声明两个decimal类型变量S1和S2,并分别赋值为1981.00m和1982.00m,然后再声明两个bool类型变量result和result1,使它们的值分别等于两种不等运算返回的值,代码如下。(实例位置:光盘\TM\sl\4\9)

        decimal S1=1981.00m;                              //声明decimal类型变量S1
        decimal S2=1982.00m;                              //声明decimal类型变量S2
        bool result;                                      //声明bool类型变量result
        bool result1;                                     //声明bool类型变量result1
        resuIt=S1 !=S2;                                   //获取不等运算返回值第一种方法
        resuIt1=!(S1==S2);                                //获取不等运算返回值第二种方法
        Console.WriteLine(result);                        //输出结果
        Console.WriteLine(result1);                       //输出结果
        Console.ReadLine();

程序的运行结果为:

        true
        true
3.小于运算符

如果要比较一个值是否小于另外一个值,可以使用小于运算符(<)。当左边的表达式的值小于右边表达式的值时,结果是真;否则,结果是假。

【例4.10】创建一个控制台应用程序,声明两个整型变量U1和U2,并分别赋值为1112和927,再声明一个bool类型变量result,使其值等于U1和U2进行小于运算的返回值,代码如下。(实例位置:光盘\TM\sl\4\10)

        int U1=1112;                                      //声明整型变量U1
        int U2=927;                                       //声明整型变量U2
        bool result;                                      //声明bool型变量result
        //使result等于U1和U2进行小于运算的返回值
        resuIt = U1 < U2;
        Console.WriteLine(result);                        //输出结果
        Console.ReadLine();

程序的运行结果为false。

说明 在用小于或大于运算符对值进行判断时,如果把判断符左右两边的值进行调换,其判断的结果也会随之改变。

4.大于运算符

如果比较一个值是否大于另外一个值,可以使用大于运算符(>)。当左边的表达式的值大于右边的表达式的值时,结果是真;否则,结果是假。

【例4.11】创建一个控制台应用程序,声明两个整型变量F1和F2,并分别赋值为18和8,再声明一个bool类型变量result,使其值等于F1和F2进行大于运算的返回值,代码如下。(实例位置:光盘\TM\sl\4\11)

        int F1=18;                                        //声明整型变量F1
        int F2=8;                                         //声明整型变量F2
        bool result;                                      //声明bool型变量result
        //使result等于F1和F2进行大于运算的返回值
        resuIt = F1 >F2;
        Console.WriteLine(result);                        //输出结果
        Console.ReadLine();

程序的运行结果为true。

5.小于等于运算符

如果要比较一个值是否小于或等于另外一个值,可以使用小于等于运算符(<=)。当左边表达式的值小于或等于右边表达式的值时,结果是真;否则,结果是假。

【例4.12】创建一个控制台应用程序,声明两个整型变量X1和X2,并分别赋值为12和9,然后再声明一个bool类型变量result,使其值等于X1和X2进行小于等于运算的返回值,代码如下。(实例位置:光盘\TM\sl\4\12)

        int X1=12;                                        //声明整型变量X1
        int X2=9;                                         //声明整型变量X2
        bool result;                                      //声明bool型变量result
        //使result等于X1和X2进行小于或等于运算的返回值
        resuIt = X2 <=X1;
        Console.WriteLine(result);                        //输出结果
        Console.ReadLine();

程序的运行结果为true。

6.大于等于运算符

大于等于运算符(>=)用于查看某个值是否大于或等于另外一个值。当运算符左边表达式的值大于或等于右边表达式的值时,结果是真;否则,结果是假。

【例4.13】创建一个控制台应用程序,声明两个整型变量T1和T2,并分别赋值为1112和927,再声明一个bool类型变量result,使其值等于T1和T2进行大于等于运算的返回值,代码如下。(实例位置:光盘\TM\sl\4\13)

        int T1=1112;                                      //声明整型变量T1
        int T2=927;                                       //声明整型变量T2
        bool result;                                      //声明bool型变量result
        //使result等于T1和T2进行大于或等于运算的返回值
        resuIt = T2 >=T1;
        Console.WriteLine(result);                        //输出结果
        Console.ReadLine();

程序的运行结果为false。

说明 关系运算符一般常用于判断或循环语句中。

4.2.4 逻辑运算符

视频讲解:光盘\TM\lx\4\05逻辑运算符.mp4

返回类型为布尔值的表达式,如关系运算符,可以被组合在一起构成一个更复杂的表达式,这是通过逻辑运算符来实现的。C#中的逻辑运算符主要包括&(&&)(逻辑与)、||(逻辑或)、!(逻辑非)。逻辑运算符的操作元必须是bool型数据。在逻辑运算符中,除了“! ”是一元运算符之外,其他都是二元运算符。表4.4给出了逻辑运算符的用法和含义。

表4.4 逻辑运算符

结果为bool型的变量或表达式可以通过逻辑运算符组合为逻辑表达式。

用逻辑运算符进行逻辑运算时,结果如表4.5所示。

表4.5 使用逻辑运算符进行逻辑运算

逻辑运算符“&&”与“&”都表示“逻辑与”,那么它们之间的区别在哪里呢?从表4.5可以看出,当两个表达式都为true时,逻辑与的结果才会是true。使用逻辑运算符“&”会判断两个表达式;而逻辑运算符“&&”则是针对bool类型的类进行判断,当第一个表达式为false时则不去判断第二个表达式,直接输出结果从而节省计算机判断的次数。通常将这种在逻辑表达式中从左端的表达式可推断出整个表达式的值称为“短路”,而那些始终执行逻辑运算符两边的表达式称为“非短路”。“&&”属于“短路”运算符,而“&”则属于“非短路”运算符。

【例4.14】创建一个控制台应用程序,在Main方法中创建整型变量,使用逻辑运算符对变量进行运算,并将运算结果输出。(实例位置:光盘\TM\sl\4\14)

        class Program
        {
            static void Main(string[] args)
            {
              int a=2;                        //声明int型变量a
              int b=5;                        //声明int型变量b
              //声明boolean型变量,用于保存应用逻辑运算符“&&”后的返回值
              bool result = ((a > b) && (a ! = b));
              //声明boolean型变量,用于保存应用逻辑运算符“||”后的返回值
              bool result2 = ((a > b) || (a ! = b));
              Console.WriteLine(result);      //将变量result输出
              Console.WriteLine(result2);     //将变量result2输出
            }
        }

程序的运行结果为:

        false
        true

4.2.5 位运算符

视频讲解:光盘\TM\lx\4\06位运算符.mp4

位运算符除按位与、按位或运算符外,其他只能用于处理整数的操作数。位运算是完全针对位方面的操作。整型数据在内存中以二进制的形式表示,如int型变量7的二进制表示是00000000 00000000 00000000 00000111。

左边最高位是符号位,最高位若是0则表示正数,若为1则表示负数。负数采用补码表示,如-8的二进制表示为11111111 11111111 11111111 11111000,这样就可以对整型数据进行按位运算。

1.“按位与”运算

“按位与”运算的运算符为“&”,“按位与”运算的运算法则是:如果两个整型数据a、b对应位都是1,则结果位才是1,否则为0。如果两个操作数的精度不同,则结果的精度与精度高的操作数相同,如图4.1所示。

2.“按位或”运算

“按位或”运算的运算符为“|”,“按位或”运算的运算法则是:如果两个操作数对应位都是0,则结果位才是0,否则为1。如果两个操作数的精度不同,则结果的精度与精度高的操作数相同,如图4.2所示。

图4.1 5&4的运算过程

图4.2 3|6的运算过程

3.“按位取反”运算

“按位取反”运算也称“按位非”运算,运算符为“~”,为单目运算符。“按位取反”就是将操作数二进制中的1修改为0,0修改为1,如图4.3所示。

4.“按位异或”运算

“按位异或”运算的运算符是“^”,“按位异或”运算的运算法则是:当两个操作数的二进制表示相同(同时为0或同时为1)时,结果为0,否则为1。若两个操作数的精度不同,则结果数的精度与精度高的操作数相同,如图4.4所示。

5.移位操作

除了上述位运算符之外,还可以对数据按二进制位进行移位操作。C#中的移位运算符有以下两种。

图4.3~7的运算过程

图4.4 10^3的运算过程

<<:左移。

>>:右移。

对于X<<N或X>>N形式的运算,含义是将X向左或向右移动N位,得到的结果的类型与X相同。在此处,X的类型只能是int、uint、long或ulong, N的类型只能是int,或者显式转换为这些类型之一,否则编译程序时会出现错误。具体执行时,左移就是将左边的操作数在内存中的二进制数据左移右边操作数指定的位数,右边移空的部分补0。右移则复杂一些。当使用“>>”符号时,如果最高位是0,左移空的位就输入0;如果最高位是1,左移空的位就输入1,如图4.5所示。

图4.5 右移

技巧 移位可以实现整数除以或乘以2的n次方的效果。例如,y<<2与y*4的结果相同;y>>1的结果与y/2的结果相同。总之,一个数左移n位,就是将这个数乘以2的n次方;一个数右移n位,就是将这个数除以2的n次方。

【例4.15】创建一个控制台应用程序,使变量intmax向左移位8次,并输出结果,代码如下。(实例位置:光盘\TM\sl\4\15)

        uint intmax=4294967295;                            //声明uint类型变量intmax
        uint bytemask;                                     //声明uint类型变量bytemask
        bytemask=intmax<<8;                                //使intmax左移8次
        Console.WriteLine(bytemask);                       //输出结果
        Console.ReadLine();

程序的运行结果为4294967040。

闯关训练:使用“按位取反”运算符对纯数字的密码进行加密,例如,有一个密码为“123456”,则其对应的二进制数为“11110001001000000”,对其进行按位取反运算之后为“00001110110111111”,该二进制数对应的十进制数为“7615”,表示密码“123456”加密之后为“7615”。

4.2.6 其他特殊运算符

视频讲解:光盘\TM\lx\4\07其他特殊运算符.mp4

C#还有一些运算符不能简单地归到某个类型中,下面对这些特殊的运算符进行详细讲解。

1.is运算符

is运算符用于检查变量是否为指定的类型。如果是,返回真;否则,返回假。

【例4.16】创建一个控制台应用程序,判断整型变量i是否为整型,可以通过下面的代码进行判断,代码如下。(实例位置:光盘\TM\sl\4\16)

        int i=0;                                           //声明整型变量i
        booI resuIt=i is int;                              //判断i是否为整型
        Console.WriteLine(result);                         //输出结果
        Console.ReadLine();

因为i是整型,所以运行程序返回值为true。

注意 不能重载is运算符。is运算符只考虑引用转换、装箱转换和取消装箱转换。不考虑其他转换,如用户定义的转换。

2.条件运算符

条件运算符(? :)根据布尔型表达式的值返回两个值中的一个。如果条件为true,则计算第一个表达式并以它的计算结果为准;如果为false,则计算第二个表达式并以它的计算结果为准。使用格式为:

        条件式?值1:值2

【例4.17】创建一个控制台应用程序,判断用户输入的年份是不是闰年,代码如下。(实例位置:光盘\TM\sl\4\17)

        static void Main(string[] args)
        {
            Console.Write("请输入一个年份:");                    //屏幕输入提示字符串
            string str=Console.ReadLine();                     //获取用户输入的年份
        int year=Int32.Parse(str);                             //将输入的年份转换成int类型
        //计算输入的年份是否为闰年
        bool isleapyear=((year%400)==0)||(((year%4)==0)&&((year%100)! =0));
        //利用条件运算符输入“是”或者“不是”
            string yesno=isIeapyear ? "是" : "不是";
            Console.WriteLine("{0}年{1}闰年", year, yesno);      //输出结果
            Console.ReadLine();
        }
3.new运算符

new运算符用于创建一个新的类型实例,它有以下3种形式。

对象创建表达式,用于创建一个类类型或值类型的实例。

数组创建表达式,用于创建一个数组类型实例。

代表创建表达式,用于创建一个新的代表类型实例。

【例4.18】创建一个控制台应用程序,使用new运算符创建一个数组,向数组中添加项目,然后输出数组中的项,代码如下。(实例位置:光盘\TM\sl\4\18)

        static void Main(string[] args)
        {
            string[] Is=new string[5];                      //创建具有5个项目的string类型数组
            ls[0]="ls1";                                    //为数组第一项赋值
            ls[1]="ls2";                                    //为数组第二项赋值
            ls[2]="ls3";                                    //为数组第三项赋值
            ls[3]="ls4";                                    //为数组第四项赋值
            ls[4]="ls5";                                    //为数组第五项赋值
            Console.WriteLine(ls[0]);                       //输出数组第一项
            Console.WriteLine(ls[1]);                       //输出数组第二项
            Console.WriteLine(ls[2]);                       //输出数组第三项
            Console.WriteLine(ls[3]);                       //输出数组第四项
            Console.WriteLine(ls[4]);                       //输出数组第五项
            Console.ReadLine();
        }

程序的运行结果如图4.6所示。

4.typeof运算符

typeof运算符用于获得系统原型对象的类型,也就是Type对象。Type类包含关于值类型和引用类型的信息。typeof运算符可以在C#语言中各种位置使用,以找出关于引用类型和值类型的信息。

【例4.19】创建一个控制台应用程序,利用typeof运算符获取引用整型的信息,并输出结果,代码如下。(实例位置:光盘\TM\sl\4\19)

        static void Main(string[] args)
        {
            Type mytype=typeof(int);                         //获取int类型的原型对象
            Console.WriteLine("类型:{0}", mytype);           //输出结果
            Console.ReadLine();
        }

程序的运行结果如图4.7所示。

图4.6 输出结果

图4.7 运行结果