C#程序设计教程
上QQ阅读APP看书,第一时间看更新

第2章 C#语法基础

C#是Visual Studio提供的主要编程语言之一,它是一种完全面向对象的、可视化的程序设计语言。掌握C#语言的代码结构、语法规则、数据类型及转换、表达式类型等最基本的语法知识是完成复杂代码编写、实现程序功能的基础。

2.1 C#变量

对用户来说,变量是用来描述一条信息的名称,在变量中可以存储各种类型的信息。而对计算机来说,变量代表一个存储地址,变量的类型决定了存储在变量中的数据的类型。简单地讲,变量就是在程序运行过程中其值可以改变的数据。程序是通过变量的名称来访问相应内存空间的。

在程序设计中,使用变量进行数据传递、数据读写等是最为基础的操作,正确理解和使用变量是程序设计工作的重要技术之一。

2.1.1 变量的命名规范

为使程序都符合相同的规范,保证一致性和统一性,要求程序必须遵守编码规范,主要内容有:代码规范、注释规范、变量命名规范、常量命名规范、类命名规范、接口命名规范、方法命名规范、文件名命名规范和程序版本号命名规范等。本节主要介绍变量的命名规范。

1.变量命名的基本原则

变量命名的基本原则如下。

1)变量名的首字符应是英文字母、下画线或符号@。

2)变量名中不能包含空格、小数点及各种符号。

3)组成变量名的字符数不要太长,应控制在3~20个字符。

4)变量名不能是C#的关键字(已被C#占用并赋予特定含义的字符串),如int、object和string等不能用作变量名。

5)变量名在同一范围内必须是唯一的。

2.为变量命名时的注意事项

在为变量命名时应注意以下几点。

1)变量名应该能够标识事物的特性,如用于存放用户名的字符串变量可使用username命名。

2)变量名应使用英文单词,尽量不要使用汉语拼音或汉字。此外,还应注意C#中的变量是区分大小写的,如变量Age和变量age将被认为是两个不同的变量。

3)变量名尽量不使用缩写,除非它能较好地表达变量数据的含义。

4)一般情况下,内存变量可使用小写单词组合。例如,bool ispass(声明一个名为ispass的、bool类型的内存变量)。类、对象及其属性和方法则应使用首字母大写的方式以示区别。例如,Student.Name(Student表示一个类,Name为类的一个属性)、PubClass.CheckUser()(PubClass表示一个类,CheckUser()表示类的一个方法)等。

3.常用的变量命名约定

在.NET Framework名称空间中有两种命名约定,即Pascal命名法和Camel(驼峰)命名法。它们都应用在由多个单词组成的名称中。

1)Pascal命名法是Pascal语言中使用的一种命名方法,组成变量名的每个单词的首字母大写,其他字母均小写,如Age、NameFirst、DateStart和WinterOfDiscontent等。

2)Camel命名法与Pascal命名法基本相同,区别是变量名的第一个单词的首字母为小写,以后的每个单词都以大写字母开头,如age、nameFirst、timeOfDeath和myNumber等。

Microsoft建议,对于简单的变量,使用Camel规则,而对于比较复杂的命名则使用Pascal规则。

2.1.2 声明变量

变量总是和变量名联系在一起的,所以要使用变量,必须为变量命名。在C#中,命名变量的过程称为“声明”。

声明变量就是把存放数据的类型告诉程序,以便为其安排需要的内存空间。变量的数据类型可以对应所有基本数据类型。声明变量最简单的格式为

数据类型名称 变量名列表;

举例如下。

float result; //声明一个单精度浮点型变量

bool usersex; //声明一个布尔型变量

decimal salary; //声明一个用于存放“工资”值的十进制变量

string username,useremail; //声明两个字符串型变量,变量名之间要使用逗号将其分隔开

语句是程序的基本组成,使用C#编写的程序的每条语句均以一个分号结束,一条语句可以书写在一行或多行中。

需要注意的是,C#使用的变量必须“先声明,后使用”。直接使用没有进行类型和名称声明的变量时,将出现未找到变量的错误。为了尽量避免这类错误,Visual Studio会将已声明的变量添加到智能感知提示选择列表中。

对于较长或拼写复杂的变量名,最好先输入首字母或前面若干个字母,再用上下光标键从供选列表中选择需要的名称,最后使用“.”号、空格键或〈Enter〉键将其输入,这样可以有效避免拼写错误。

2.1.3 给变量赋值

一个变量只有在被赋予某数据(值)后,才有实际意义。为变量赋值需要使用赋值号“=”。

1.赋值表达式

C#的赋值表达式由变量、赋值号和值表达式组成,变量总是出现在赋值号的左边。举例如下。

int num;

num=32; //为整型变量num赋值32

bool usersex=true; //声明布尔型变量usersex的同时赋值为true

给字符和字符串变量赋值,举例如下。

char letter; //声明一个字符型变量(字符型变量只能存放一个字符,不同于字符串型)

letter='w';

string uname="张三"; //声明字符串变量uname的同时为其赋值“张三”

2.使用变量为变量赋值

C#的赋值表达式中的值表达式可以是另一个变量,举例如下。

bool db_open,db_close;

db_open=true;

db_close=db_open; //将变量db_open的值赋给同类型变量db_close

//将文本框控件textBox1中Text属性值(文本框中的文本)保存到字符串变量uname中

string uname=textBox1.Text;

3.同时为多个变量赋值

可以同时为几个变量赋以相同的值,举例如下。

int num1,num2,num3;

num1=num2=num3=7;

需要说明的是,赋值号“=”与数学中的等号具有相同的外观,但它们的含义是完全不同的。例如,在数学中x=12与12=x均正确,但在赋值语句中x=12是正确的,而12=x就是错误的,因为语法格式要求变量只能出现在赋值表达式的左边。

2.1.4 变量的作用域

在面向对象的程序设计中,变量的作用域(有效范围)是一定的。在声明变量时可使用访问修饰符来对变量进行访问控制。C#中常用的访问修饰符及说明如表2-1所示。

表2-1 常用访问修饰符及指定的变量作用域

978-7-111-59051-4-Chapter02-1.jpg

除了使用访问修饰符外,在程序不同位置声明的变量,其含义及作用域也是不同的。常用的有静态变量、实例变量和局部变量等概念。举例如下。

978-7-111-59051-4-Chapter02-2.jpg

其中,x为静态变量,y为实例变量,i是局部变量。

1)静态变量:指使用static修饰符声明的变量,它只需创建一次,在后面的程序中可以多次引用。若类中的一个成员变量被声明为静态的,则类中的所有成员都可以共享这个变量。

2)实例变量:指未用static修饰符声明的变量,如上述代码中的y。实例变量的作用域为从某个类的实例被创建,一直到该实例从内存中被释放。

3)局部变量:指在一个独立的程序块中声明的变量,如上述代码中的i。局部变量只在声明它的程序块中有效,一旦程序离开这个范围局部变量立即失效。在if、switch、for和while等块结构语句中声明的变量都是局部变量。

2.2 数据类型及类型转换

程序在处理数据时,需要对数据进行临时保存,而保存不同类型的数据所用的存储空间是不同的,所以掌握各种数据类型及其转换方法是十分重要的。

根据数据的性质不同,可以将其分为数值型数据、字符型数据、日期时间型数据、逻辑型数据和对象型数据等。在程序设计过程中,除了需要理解各种类型的数据特点外,还需要掌握常用数据类型之间的转换,以便对数据进行存储、输出或加工等操作。

2.2.1 数值类型

数值类型有整数类型与实数类型两种,没有小数位的为整数类型,带小数位的为实数类型。

1.整数类型

整数类型又分为有符号整数与无符号整数。有符号整数可以带正负号,无符号整数不需带正负号,默认为正数。

有符号整数包括sbyte(符号字节型)、short(短整型)、int(整型)和long(长整型)。

无符号整数包括byte(字节型)、ushort(无符号短整型)、uint(无符号整型)和ulong(无符号长整型)。

需要注意的是,不同的整数类型表示的数值范围不同,这为程序设计中根据实际需要进行灵活选择提供了方便,同时设置适当的类型对节约系统资源、提高程序运行效率也是十分重要的。

常用整数类型、占用的存储空间及取值范围如表2-2所示。

表2-2 整数类型及说明

978-7-111-59051-4-Chapter02-3.jpg

2.实数类型

实数类型主要包括float(单精度浮点型)、double(双精度浮点型)和decimal(十进制型)。

常用实数类型占用的存储空间及取值范围如表2-3所示。

表2-3 实数类型及说明

978-7-111-59051-4-Chapter02-4.jpg

float型数据可表示的精度为7位;double型数据可表示的精度为15位或16位;decimal型数据可以表示28位或29位有效数字,特别适合财务和货币计算时使用。

2.2.2 字符类型

字符型数据包括单个字符类型与多个字符(字符串)类型。

1.Unicode字符集

Unicode是一种重要的通用字符编码标准,它覆盖了美国、欧洲、中东、非洲和亚洲的语言,以及古文和专业符号。Unicode允许交换、处理和显示多语言文本,以及公用的专业和数学符号。

Unicode字符适用于所有已知的编码。Unicode是继ASCII(美国国家交互信息标准编码)字符码后的一种新字符编码,如UTF-16允许用16位字符组合为一百万或更多的字符。C#提供的字符类型按照国际标准采用了Unicode字符集。

2.char(字符型)

char(字符型)的数据范围是0~65535的Unicode字符集中的单个字符,占用2字节。

char表示无符号16位整数,char(字符型)的可能值集与Unicode字符集相对应。虽然char型数据的表示形式与ushort(短整型)相同,但ushort与char意义不同,ushort代表的是数值本身,而char代表的则是一个字符。举例如下。

char FirstChar='A'; //字符型常量必须加单引号来表示

3.string(字符串型)

string(字符串型)是指任意长度的Unicode字符序列,占用字节根据字符多少而定。

string表示包括数字与空格在内的若干个字符序列,允许只包含一个字符的字符串,甚至可以是不包含字符的空字符串。举例如下。

string UserName="zhangsan"; //字符串型常量必须加双引号来表示

string UserPwd=""; //连续两个双引号表示空字符串

2.2.3 布尔类型和对象类型

bool(布尔型):表示布尔逻辑型数据,其值只能是true(真)或false(假)。需要注意的是,true和false是C#的关键字,不能用来定义其他对象的名称。

bool型数据为程序进行复杂的判断提供了数据类型依据,另外,在程序进行关系运算或逻辑运算时,也将产生bool型数据结果,所以bool类型数据也常被称为逻辑型数据。

object(对象型)是所有其他类型的最终基类,其占用字节视具体表示的数据类型而定。C#中的每种类型都是直接或间接从object类型派生的,object表示一个通用类型。一个object类型的变量可以存放任何其他类型的数据。

2.2.4 数据类型转换

在程序处理数据的过程中,经常需要将一种数据类型转换为另一种数据类型。例如,用户在文本框中输入的数据,若需对其进行数学运算,则首先要将其类型由字符串型转换为数值类型;而需要显示到标签控件中的数字却需要首先将其转换成字符串类型。在C#中,数据类型的转换分为“隐式转换”与“显式转换”两种。

1.隐式转换

隐式转换是系统自动执行的数据类型转换。隐式转换的基本原则是允许数值范围小的类型向数值范围大的类型转换,允许无符号整数类型向有符号整数类型转换。举例如下。

int x=123456; //为int类型变量赋值

long y=x; //将x的值读取出来,隐式转换为long类型后,赋给长整型变量y

uint a=123456; //为无符号整型变量a赋值

long b=a; //将a的值读取出来,隐式转换为有符号的长整型后,赋给长整型变量b

C#允许将char(字符)类型的数据隐式转换为数值范围在短整型(含短整型)以上的数值类型。举例如下。

char mychar='A'; //为字符型变量mychar赋值

//读取mychar的值,隐式转换为整数65(A的ASCII码值),与32相加后将结果赋给num

int num=32+mychar;

之所以允许将字符型数据隐式转换为整数,是因为char类型的数据在内存中保存的实质是整型数据,只是从意义上代表的是Unicode字符集中的一个字符。

在数据之间进行隐式转换,通常是从低精度的数据类型向高精度的数据类型转换,它一般不会失败,也不会导致信息丢失。

2.显式转换

显式转换也称为强制转换,是在代码中明确指明将某一类型的数据转换为另一种类型。显式转换语句的一般格式为

类型A变量=(类型A)类型B变量; //将类型B变量中的数据转换成类型A

举例如下。

int x=600;

short z=(short)x;

将变量x中的值显式地转换为short类型,赋值后,变量z的值为600。

实际上,显式转换包括了所有的隐式转换,也就是说把任何隐式转换写成显式转换的形式都是允许的。与隐式转换相同,使用显式转换同样可能出现精度下降的情况。举例如下。

decimal d=234.55M; //应使用M或m类型符说明类型,否则系统会提示出错

//将十进制变量d中的数据(234.55)转换为整型后,赋值给整型变量x

int x=(int)d;

将十进制型变量d的值显式转换为整型后,其小数部分将被截去,x得到的赋值为234。

3.使用方法进行数据类型的转换

有时通过隐式或显式的转换都无法将一种数据类型转换为另一种数据类型,例如,在程序设计中经常遇到的,将数值类型转换为字符串类型,或将字符串类型转换为数值类型。这种情况通常发生在需要使用文本框中的数据进行数学运算,或者将数值类型的数据显示在文本框中时。由于文本框的Text属性是字符串类型,因而必须进行这种数据类型的转换。为解决类似问题,C#提供了一些专门用于数据类型转换的方法。

(1)Parse方法

Parse方法用于将特定格式的字符串转换为数值,其语法格式为

数值类型变量=数值类型.Parse(字符串型表达式);

其中“字符串型表达式”的值必须严格符合“数据类型名称”对数值格式的要求。举例如下。

int x=int.Parse("123"); //将整型字符串转换为对应的整型数据

float f=float.Parse("123.45"); //将单精度型字符串转换为对应的单精度数据

Parse方法也可用于将包含单个字符的字符串数据转换为char类型。举例如下。

char mychar=char.Parse("A") //将包含单个字符的字符串转换为char类型

(2)ToString()方法

ToString()方法可将其他数据类型的变量值转换为字符串类型。其方法格式为

String类型变量=其他类型变量.ToString();

举例如下。

int x=123;

string s=x.ToString(); //将整型变量x的值读取出来,转换为字符串"123",然后赋值给s

decimal y=10M/3M; //使用标识符M表示这是两个decimal类型数据相除

label1.Text=y.ToString("f"); //将变量y的值显示到标签控件中,保留2位小数点(得到3.33)

label2.Text=y.ToString("f4"); //保留4位小数点(得到3.3333)

(3)Convert类

Convert类包含了众多进行数据类型转换的方法,如表2-4所示。

表2-4 Convert类包含的常用类型转换方法

978-7-111-59051-4-Chapter02-5.jpg

2.3 运算符与表达式

描述各种不同运算的符号称为运算符,而参与运算的数据称为操作数。表达式用来表示某个求值规则,它由运算符、配对的圆括号,以及常量、变量、函数和对象等操作数组合而成。表达式可用来执行运算、处理字符串或测试数据等,每个表达式都产生唯一的值。表达式的类型由运算符的类型决定。

2.3.1 运算符与表达式类型

根据运算符的不同,C#将运算符和表达式分为以下5种类型:算术运算符和算术表达式、字符串运算符和字符串表达式、位运算符和位运算表达式、关系运算符和关系表达式、布尔运算符和布尔表达式。

1.算术运算符与算术表达式

算术运算符包括一元运算符与二元运算符。

由算术运算符与操作数构成的表达式称为算术表达式。

(1)一元运算符

一元运算符包括:-(取负)、+(取正)、++(增量)、--(减量)。

一元运算符作用于一个操作数,其中“-”与“+”只能放在操作数的左边,表示操作数为负或为正。

增量与减量符只能用于变量,不能用于常量。表示操作数增1或减1。举例如下。

int x=10;

++x; //增量,x的值为11,等价于x=x+1

x=5;

x--; //减量,x的值为4,等价于x=x-1

增量与减量运算符既可以放在操作数的左边,也可以放在操作数的右边。如果在赋值语句中使用增量或减量运算符,其出现的位置不同,具有的含义也不同。

若增量或减量运算符出现在操作数的左侧,表示将操作数先执行增量或减量,再将增(减)结果赋值给“=”左侧的变量。

若增量或减量运算符出现在操作数的右侧,表示先将未执行增(减)量操作的操作数赋值给“=”左侧的变量,再执行增量或减量操作,并将增(减)结果保存在操作数中。举例如下。

int a,b,c,d;

a=b=10;

c=++a; //先执行增量,再执行赋值,c的值为11

c=b++; //先执行赋值,再执行增量,c的值为10

d=b; //b在上一语句中已执行了增量,故d的值为11

(2)二元运算符

二元运算符包括:+(加)、-(减)、*(乘)、/(除)、%(求余)。其意义与数学中相应运算符的意义基本相同。

说明:%(求余)运算符是以除法的余数作为运算结果,故求余运算也称为模运算。举例如下。

int x=6,y=4,z;z=x%y; //z的值为2,即6被4除得余数2

z=y%x; //z的值为4,即4被6除得商0,得余数4

在C#中,求余运算符不仅支持整型数值的运算,也支持实型数值的运算。例如,5%1.5的结果为0.5。

(3)算术表达式

算术表达式是指使用若干二元运算符、数学方法、括号和操作数等元素共同组成的数学式子,与大家熟悉的数学表达式十分相似。举例如下。

int a,b,c;

c=a*b/(32+b%3); //由运算符、操作数和括号组成的算术表达式

需要注意的是,在算术表达式中所有的括号都要使用圆括号“()”,不能使用“[]”和“{}”。此外,在使用算术表达式时,要特别注意数据类型对最终计算结果的影响。

在使用算术表达式时应特别注意变量的类型,不同数据类型的变量中存储的数据也可能是不同的,尽管这些数据都是来自相同的计算结果。举例如下。

int a,b=39;

a=b/2; //a的值为19,而不是19.5

这是由于相除的两个数都是整型,结果也是整型,小数部分被截去。即使被赋值的是实型变量,两个整型数相除,也不会保留相除结果的小数部分。举例如下。

double x;

int a=37,b=4;

x=a/b; //x的值是9而不是9.25

这是由于a和b都是整型,所以运算的结果只能是整型,这个整型结果在赋给双精度变量x时,才被隐式转换为双精度型。因此,x的值自然是9而不是9.25。

两个整型数相除如果想保留住小数,必须进行显式转换。举例如下。

double x;

int a=37,b=4;

x=(double)a/b; //x的值是9.25

由于a被强制转换为双精度型,则b在运算前也被隐式转换为双精度型(向数值范围宽的类型转换),运算的结果自然也是双精度型。

2.字符串运算符与字符串表达式

字符串表达式由字符串常量、字符串变量、字符串方法和字符串运算符组成。C#提供的字符串运算符只有一个“+”,它用于连接两个或更多的字符串。

当两个字符串用连接运算符“+”连接起来后,第二个字符串直接添加到第一个字符串的尾部,得到一个包含两个源字符串全部内容的新的字符串。如果要把多个字符串连接起来,每两个字符串之间都要用“+”分隔开。举例如下。

string str="中国"+"人民"; //连接后结果为:"中国人民"

string str="ABC"+"D"+"EFG"; //连接后结果为:"ABCDEFG"

string str="12 3"+"45"+"67"; //连接后结果为:"1234567"

字符串连接运算符“+”还可以将字符型数据与字符串型数据或多个字符型数据连接在一起,得到的结果为一个新字符串。举例如下。

string str='E'+"abcd"+'F'; //str的值为“EabcdF”

3.关系运算符与关系表达式

(1)关系运算符

关系运算符用于对两个操作数进行比较,判断关系是否成立,若成立则结果为true,否则为false,即关系运算符的运算结果为布尔型。常用的关系运算符及说明如表2-5所示。

表2-5 C#中常用的关系运算符

978-7-111-59051-4-Chapter02-6.jpg

需要注意以下两点。

1)等于运算符由两个连续的等号“==”构成,以区别于“=”(赋值号)运算符。

2)凡是由两个符号构成的关系运算符(如==、>=、<=、!=),在使用时两个符号之间不能有空格,否则将出错。

(2)关系表达式

关系表达式由操作数和关系运算符组成。关系表达式中既可以包含数值,也可以用于字符或字符串,但是用于字符串的关系运算符只有相等(==)和不等(!=)两种运算符。

下面的代码给出了常见的关系表达式使用方法。

int a=5,b=3;

char ca='A',cb='B';

string sa="abcd",sb="abc";

bool i,c,s;

i=a>b; //先进行a>b的比较,然后把比较结果true赋值给i

c=ca>cb; //c的值为false

s=(sa==sb); //s的值为false

需要说明的是,在进行字符或字符串比较时,实际上比较的是字符的Unicode值。上例中两个字符变量的比较,由于A的ASCII码值小于B的ASCII码值,所以ca>cb的关系不成立,运算的结果为false。

字符串的比较与字符比较道理相同,相等运算要求两个字符串的个数与相应位置上的字符完全相同时运算结果为true,否则运算结果为false。

4.逻辑运算符与逻辑表达式

逻辑表达式(也称为“布尔表达式”)由关系运算符、逻辑运算符(也称为“布尔运算符”)连接常量或关系表达式组成,其取值为布尔值(true或false)。通过条件表达式或逻辑表达式可对应用程序计算结果及用户输入值进行判断,并根据判断结果选取执行不同的代码段。

逻辑运算符的操作数是布尔类型,运算结果也是布尔类型。在C#中,最常用的逻辑运算符是!(非)、&&(与)、||(或)。

“非”运算是一元运算符,是求原布尔值相反值的运算,如果原值为真,非运算的结果为假,否则为真。

“与”运算是求两个布尔值都为真的运算,当两个布尔值都为真时,运算结果为真,即所谓同真为真。

“或”运算是求两个布尔值中至少有一个为真的运算,当两个布尔值中至少有一个为真时运算结果为真,只有在两个布尔值均为假时,运算结果才为假,即所谓同假为假。举例如下。

bool b1=!(5>3); //b1的值为false

bool b2=(5>3)&&(1>2); //b2的值为false

bool b3=(5>3)||(1>2) //b3的值为true

5.赋值运算符与赋值表达式

在赋值表达式中,赋值运算符左边的操作数称为左操作数,赋值运算符右边的操作数称为右操作数。其中左操作数必须是一个变量或属性,而不能是一个常量。

前面介绍过的赋值运算符“=”称为“简单赋值运算符”,它与其他算术运算符结合在一起可组成“复合赋值运算符”,如*=、/=、%=、+=、-=等。C#中常用的复合运算符及等价关系如表2-6所示。

表2-6 C#中常用的复合运算符

978-7-111-59051-4-Chapter02-7.jpg

赋值表达式的一般格式为

左操作数 赋值运算符 右操作数;

使用复合赋值运算符时,系统先将左操作数与右操作数进行“其他运算符”要求的运算,然后再将运算结果赋值给左操作数。例如,x+=y表示先执行x+y的运算,然后再将运算结果赋值给x,所以x+=y等效于x=x+y。

6.条件赋值运算符及表达式

条件赋值表达式可以看作是逻辑表达式和赋值表达式的组合,它可根据逻辑表达式的值(true或false)返回不同的结果。条件运算符由符号?与:组成,通过操作3个操作数完成运算,其一般格式为

变量=关系达式?表达式1:表达式2;

条件赋值表达式在运算时,首先运算“关系表达式”的值,如果为true,则运算结果为“表达式1”的值,否则运算结果为“表达式2”的值。举例如下。

int x,y;

x=400;

y=x>500?x*0.8:x*0.9; //y的值为360

由于x的值为400,小于500,故条件赋值表达式执行时将返回后一个表达式(x*0.9)的值。

条件赋值表达式也可以嵌套使用,举例如下。

int x=100,y=100;

string s;

s=x>y?"greater than":x==y?"equal to":"lessthan"; //s的结果为equalto

上例中的条件赋值表达式对照一般格式分析,其中布尔类型表达式为“x>y”,表达式1为“"greater than"”,表达式2本身又是一个完整的条件赋值表达式“(x==y?"equal to":"less than")”。

显然,通过条件赋值表达式的嵌套,可以实现多分支的选择判断。

2.3.2 运算符的优先级与结合性

运算符的优先级与结合性本质上都是运算顺序问题,优先级是指当一个表达式中出现不同的运算符时,先进行何种运算。结合性是指当一个表达式中出现两个以上的同级运算符时,是由左向右运算还是由右向左运算。

1.优先级

运算符的优先级具有以下几个特点。

1)一元运算符的优先级高于二元和三元运算符。

2)不同种类运算符的优先级有高低之分,算术运算符的优先级高于关系运算符,关系运算符的优先级高于逻辑运算符,逻辑运算符的优先级高于条件运算符,条件运算符的优先级高于赋值运算符。

3)有些同类运算符优先级也有高低之分,在算术运算符中,乘、除、求余的优先级高于加、减;在关系运算符中,小于、大于、小于或等于、大于或等于的优先级高于相等与不等;逻辑运算符的优先级按从高到低排列为非、与、或。

事实上,一个表达式常常是各种运算符混合在一起使用的,当一个表达式中包含不同类型的运算符时,将按照各运算符优先级的不同安排运算顺序。举例如下。

bool b=5*2+8>=9*8||"ABC"=="ABC"&&!(3-2<3*5);

上述表达式的运算执行过程如下。

1)先运算括号内的表达式,括号内的表达式先运算“3*5”结果为15,再运算“3-2”结果为1,然后运算“1<15”,结果为true,这时整个表达式运算的中间结果为“5*2+8>=9*8||"ABC"=="ABC"&&!true”。

2)由于一元运算符的优先级高于二元运算符,所以在第1)步中得出的中间结果的基础上先运算“!true”,结果为false,得出的中间结果为“5*2+8>=9*8||"ABC"=="ABC"&&false”。

3)在第2)步的中间结果中,优先级最高的是算术运算符,而算术运算符中乘运算符又高于加运算符,所以先运算“5*2”与“9*8”,结果分别为10与72,然后运算“10+8”,结果为18,至此算术运算全部完成,表达式中只剩下关系运算符与逻辑运算符,其中间结果为

18>=72||"ABC"=="ABC"&&false

4)在第3)步的中间结果中,关系运算符优先级高于逻辑运算符,而关系运算符中“>=”运算符的优先级又高于“=”运算符,所以先运算18>=72结果为false,再运算"ABC"=="ABC",结果为true,其中间结果为

false||true&&false

5)表达式运算到第4)步,只剩下逻辑或(||)运算符和逻辑与(&&)运算符,由于与运算符的优先级高于或运算符,所以先运算“true&&false”,根据与运算“同真为真”的规则,运算结果为false,表达式的中间结果为“false||false”,最后进行或运算,根据“同假为假”的规则,最终运算结果为false。

2.圆括号

为了使表达式按正确的顺序进行运算,避免实际运算顺序不符合设计要求,同时为了提高表达式的可读性,可以使用圆括号明确运算顺序。举例如下。

string s=x>y?"greater than":x==y?"equal to":"less than";

上述表达式是一个正确的表达式,但为了提高表达式的可读性,可以添加括号使之成为

string s=x>y?"greater than":(x==y?"equal to":"less than");

使用括号还可以改变表达式的运算顺序。例如,b*c+d的运算顺序是先进行“b*c”的运算,然后再加“d”,如果表达式加上括号,变为b*(c+d),则运算时会先进行括号内的运算,然后将结果乘“b”。

3.结合性

在多个同级运算符中,赋值运算符与条件运算符是由右向左结合的,除赋值运算符以外的二元运算符是由左向右结合的。例如,x+y+z是按(x+y)+z的顺序运算的,而x=y=z是按x=(y=z)的顺序运算(赋值)的。

2.4 C#常用方法与属性

为了方便程序设计中各种数据类型的处理,C#提供了丰富的类方法与类属性,使用这些方法与属性,可以提高程序设计的效率。在.NET中为了管理方便,而将各种类、对象划分到不同的“命名空间”(Namespace)中,各命名空间中又可能包含子空间。在使用类和对象时,如果对应的命名空间尚未使用using命令引用将会出现错误。

2.4.1 日期时间类常用方法与属性

C#中的DateTime类提供了一些常用的日期时间方法与属性,该类属于System命名空间。在使用模板创建应用程序时,该命名空间的引用已自动生成,因此可以直接使用DateTime类。对于以当前日期时间为参照的操作,可以使用该类的Now属性及其方法。

以2017年7月31日星期一,16点17分25秒的当前日期时间为例,日期时间类的Now属性的常用方法与属性如表2-7所示。

表2-7 日期时间类的常用方法与属性

978-7-111-59051-4-Chapter02-8.jpg

2.4.2 常用数学方法与属性

C#中的Math类提供了一些常用的数学方法与属性,该类属于System命名空间。Math类是一个密封类,有两个公共属性和若干静态数学方法。Math类常用的属性与方法如表2-8所示。

表2-8 数学类常用属性与方法

978-7-111-59051-4-Chapter02-9.jpg

(续)

978-7-111-59051-4-Chapter02-10.jpg

2.4.3 常用字符串方法与属性

任何字符串变量与常量对象都具有字符串的方法与属性,可以使用这些方法与属性来处理字符串。假设有一个字符串变量s,其值为“abCDeFg”(注意,该字符串前两个字符为空格),则s就具有如表2-9中所示的字符串常用方法与属性。

表2-9 处理字符串常用方法与属性

978-7-111-59051-4-Chapter02-11.jpg

2.4.4 随机方法

Random类提供了产生伪随机数的方法,该方法必须由Random类创建的对象调用。Random类创建对象的格式为

Random随机对象名称=new Random();

如果要声明一个随机对象r,则代码为

Random r=new Random();

现假定已经声明了一个随机对象r,则随机方法的使用如表2-10所示。

表2-10 常用随机方法

978-7-111-59051-4-Chapter02-12.jpg

需要说明的是,使用Random对象产生某区间内的随机整数时,下界包含在随机数内,而上界不包含在随机数内。例如,随机数中包含1,但不包含10,即随机数范围为1~9。

Random rd=new Random();

in tNum=rd.Next(1,10);

2.5 实训 C#数据类型与常用方法

2.5.1 实训目的

了解C#语言的语法规则,理解与掌握C#各种基本数据类型的知识。理解表达式的概念及作用,根据需要正确设计各种类型的表达式。掌握处理各种数据类型常用的方法、属性和字段,根据需要灵活运用,以提高程序代码设计效率。

2.5.2 实训要求

设计一个Windows应用程序,程序启动时显示如图2-1所示的界面。单击不同的按钮页面中将显示对应数据类型常用方法的使用示例。图2-2所示为“日期时间”按钮被单击时显示的结果,图2-3所示为“数学”按钮被单击时显示的结果,图2-4所示为“字符串”按钮被单击时显示的结果,图2-5所示为“随机数”按钮被单击时显示的结果。

978-7-111-59051-4-Chapter02-13.jpg

图2-1 程序初始界面

978-7-111-59051-4-Chapter02-14.jpg

图2-2 日期时间类型常用方法

978-7-111-59051-4-Chapter02-15.jpg

图2-3 常用数学方法

978-7-111-59051-4-Chapter02-16.jpg

图2-4 常用字符串方法

978-7-111-59051-4-Chapter02-17.jpg

图2-5 常用随机数方法

2.5.3 实训步骤

1.设计程序界面

新建一个Windows应用程序项目,向窗体中添加1个用于显示输出信息的标签控件label1和4个按钮控件button1~button4。

2.设置各控件的属性

在设计视图中选中label1控件,在“属性”窗口中设置其Name属性为lblResult;分别选中4个按钮控件,设置它们的Name属性分别为btnDataTime、btnMath、btnSting和btnRandom,设置它们的Text属性分别为“日期时间”“数学”“字符串”和“随机数”。

3.编写程序代码

在设计视图中双击某对象可切换到代码窗口,并由系统自动创建该对象的默认事件框架。例如,双击窗体将切换到代码窗口,并由系统自动创建一个名为Form1_Load的事件处理程序框架。

所谓“事件”,是指用户或系统对程序执行了某种操作,如页面加载、单击按钮或更改选项等。“事件过程”是指当某事件发生时执行的程序代码段。例如,书写在Form1_Load事件过程中的代码,当窗体装入时会自动被执行;书写在button1_Click事件过程中的代码,在用户单击按钮button1时将被自动执行,这就是Visual Studio的事件驱动编程模式。

窗体装入时执行的事件过程代码如下。

978-7-111-59051-4-Chapter02-18.jpg

“时间日期”按钮被单击时执行的事件处理程序代码如下。

978-7-111-59051-4-Chapter02-19.jpg

“数学”按钮被单击时执行的事件处理程序代码如下。

978-7-111-59051-4-Chapter02-20.jpg

978-7-111-59051-4-Chapter02-21.jpg

“字符串”按钮被单击时执行的事件处理程序代码如下。

978-7-111-59051-4-Chapter02-22.jpg

“随机数”按钮被单击时执行的事件处理程序代码如下。

978-7-111-59051-4-Chapter02-23.jpg

说明:

1)双引号是字符串常量的定界符,若字符串的内容中也使用了双引号,则应当使用“\"”转义符,否则程序将出错。

2)为了使标签控件中的文字产生换行,程序中使用了表示换行符的转义符“\n”("\n\n"表示产生两个换行符,使行与行之间保留一个空行)。

3)程序中使用了复合运算符“+=”。如,“x+=y;”等效于“x=x+y;”。