您的位置:首页 > 编程语言 > C#

C#学习笔记—语法基础

2012-09-05 10:01 573 查看
计算机程序处理的就是一系列的数据操作,每一个操作都会改变计算机内存地址中的所存储的内容。
空格、制表符和回车符统称为空白字符。C#编译器不考虑(忽略)空白字符。代码块可以包含任意条(包括0)C#语句。编码中的缩进写法只是为类提高程序的可读性,同样,在C#代码中,一个重要的编码原则是编写个可读性强的代码,而不是为了缩短代码行数而敲写简短的代码行。代码块可以相互嵌套。严格的讲,注释不是C#的代码,只是为了提高程序的可读性。注释分为单行注释(单行注释有// 和///),多行注释。C#代码同样是区分大小写。以#开头的任意关键字实际上都是一个预处理指令,但这些并不是严格意义上的C#关键字。

C#声明变量的语法为:<varType> <varName>;,使用未声明的变量时,编译器会报错;另,声明的变量未初始化也同样报错。变量在使用之前必须初始化。C#中,可以使用的变量类型有无限多,这是 因为开发可以设计属于自己的类类型。

C#中的基本数据类型,也称为预定义类型。包括8中整数类型,2种用于科学计算的浮点型(float的有效位数为7~8,double的有效位数为15~16),1种用于金融的浮点数据类型(demical的有效位数貌似是28),布尔数据类型,字符数据类型,字符串类型。另外,需要注意的是:int、uint、sbyte.......等在C#中使用的类型名称,它们在.NET FrameWork中的真正名称是(System.Int32、System.UInt32、System.SByte.......等),int、uint、sbyte.......等都是在Framework中定义的别名。

C#编译器拒绝分布在多行的字符串字面值。变量名(标识符)的命名规则中,变量名的第一个必须是字母或下划线或@。变量名(或标识符)命名有些常用的约定,在C#中,变量名(标识符)一般采用camelCase,函数名(标识符)通常是采用PascalCase,这两种命名方式是.NET FrameWork中的命名约定。

字面值,通常也称为硬编码。有字符串字面值和数字的字面值。数字的字面值中,为了给特定类型的变量赋值,可以在数字字面值添加后缀(15U,10.1F,100UL,1.5M等)。

在字符串字面量前头添加“@”,可以实现逐字地指定字符串。即两个双引号之间的所有字符都包含在字符串中,包括行末字符和需要转义的字符。唯一例外是双引号字符的转义,它们必须指定,以避免结束字符串。逐字指定字符串在文件名中非常有用,因为文件名中大量使用了反斜杠字符。

C#中的运算符可分为3类(按操作数的个数划分):一元运算符,处理一个操作数;二元运算符,处理两个操作数;三元运算符,处理三个操作数。

C#中的名称空间,是.NET中提供应用程序代码容器的方式。这样,就可以唯一地标识代码及其内容。名称空间也用作.NET Framework中给项分类的一种方式。大多数项都是类型定义。在默认情况下,C#代码包含在全局名称空间中。这意味着对于包含在这段代码中的项,只要按照名称进行引用,就可以由全局名称空间中的其他代码访问它们。可以使用关键字namespace为花括号中的代码块显式定义名称空间。如果在该名称空间代码的外部使用名称空间中的名称,就必须写出该名称空间中的限定名称。System名称空间是.NET
Framework应用程序的根名称空间,包含控制台应用程序所需要的所有基本功能。

程序的流程有顺序、分支和循环3种。

bool类型的变量有两个值,分别是true和false。

&&、||和&、|操作的结果相同,但性能不同;前者的第二个操作数的操作是根据第一个操作数的操作结果而定的,而后者则是两个操作数都要进行操作,且是用于按位运算。

C#允许给代码行加上标签,这样,可以使用goto语句直接跳转到这些代码行上。语法:goto <LabelName>;

三元运算符,语法:<test>?<resultIfTrue>:<resultIfFasle>。

if语句、if……else语句、if……elseif……else语句,注意if和else的嵌套配对,并且这些都是看成一条语句的,而不是多条。

switch分支语句的语法:switch(<testVar>){case <comparisonVar1>:<code>;break;...;default:<code>; break;}。执行第一个case语句,(在C#中)接着执行第二个case语句是非法的,而在C++中,这是允许的,所以,在case语句中,必须要有break语句。但允许多个case语句堆叠起来,即是判断多个条件后执行分支语句。另,就是,default语句不要求一定要放在列表中的最后,还可以和case语句放在一起。comparisonVar都必须是常量。

循环语句有:for、foreach、do……while和while。

C#中提供了4中中断循环的命令:break——立即终止循环;continue——立即终止当前的循环(跳入到下一次循环中);goto——可以跳出循环到指定的位置;return——跳出循环及其包含的函数。

类型的转换就是把数值从一种类型转换成另一种类型,C#中的数据类型转换包括隐式转换和显式转换。

隐式转换:从类型A到类型B的转换可以在所有的情况下进行,执行转换是编译器完成的,不需要添加额外的代码。

显式转换:从类型A到类型B转换只能在某些情况下进行,转换的过程应进行某种类型的处理,显式转换需要添加额外的代码。

一个类型的数据变量,只要其值(范围)包含在另一类型内,就可以进行安全的隐式转换。隐式转换不需要额外的代码,而显式转换时需要额外的代码的。(bool和string类型是没有隐式转换的,如果需要进行转换,需要采用显式转换)

类型转换Convert、Parase和TryParase的区别

范例:Convert.ToInt32、int32.Parase和int32.TryParase都是将类型转换成int,但它们存在区别

Convert.ToInt32与int.Parase较为类似,实际上Convert.ToInt32内部调用了int.Parase。

Convert.ToInt32参数为null时,返回0;int.Parase参数为null时,抛出异常。

Convert.ToInt32参数为""时,抛出异常;int.Parase参数为“”时,抛出异常。

Convert.ToInt32可以转换的类型较多;int.Parase只能转换字符型字符串。

Int.TryParase与Int.Parase又较为类似,但它不会抛出异常,转换成功返回true,转换失败返回false。最后一个参数为输出值,如果转换失败,输出值为0。

两个关键字checked和unchecked,称为表达式的溢出检查环境。语法:checked(expression); unchecked(expressiong);

使用checked进行溢出环境检查时,当数据类型转换时出现溢出,那么程序会抛出一个异常,中断程序执行。

使用Convert命令进行显式转换的有Convert.ToBoolean(val);Convert.ToByte(val);Convert.ToChar(val);Convert.ToDecimalval);Convert.ToDouble(val);Convert.ToInt16(val);Convert.ToInt32(val);Convert.ToInt64(val);Convert.ToSByte(val);Convert.ToSingle(val);

使用Convert进行数据类型的显式转换,总是进行溢出检查的,与checked和unchecked关键字以及项目属性设置就不起作用了。

其中,val可以是各种类型的变量,如果Convert不能处理该类型的变量,编译器会告诉用户的。这些转换总是要进行溢出检查。

3种简单的组合数据类型:

枚举——变量类型,用户定义的一组可能的离散值;

结构——合成的变量类型,由基本数据类型(通常只包含基本的变量字段)组合成的一种数据类型;

数组——包含一种类型的多个变量,通过下标访问元素的一种数据类型。

需要注意的是,对计算机来说,所有类型的数据都是一系列的位,即一组0和1。变量的含义是通过解释这些数据的方式来传达的。

但是在一般情况下,不同类型的变量使用不同的模式来表示数据。

枚举类型的声明与变量声明初始化语法:使用关键字enum,

语法:enum typeName{val1,val2,val3,...valN}

接着 <typeName> <varName>,赋值是varName=typeName.value;。枚举使用一个基本类型来存储,默认情况下,该类型是int。但在枚举声明中添加类型,就可以指定其他基本类型,enum typeName:short{val1,val2,val3,...valN}。枚举的基本类型可以是byte、sbyte、short、ushort、int、uint、long和ulong。在默认的情况下,每个值都会根据定义的顺序(从0开始),自动赋给对应的基本类型值。也可以重写这个赋值过程来指定每个枚举的实际值。还可以使用一个值作为另一个枚举值的基础值,也可以为多个枚举指定相同的值。没有赋值的任何值都会自动获得一个初始值,这里使用的值是从比最后一个明确声明的值大1开始的序列。

范例:

enumcolor:int enum userName:byte

{ {

red=1, Lily=3,

green=2, Sam,

black=3, John=7,

…… Tom

blue =7 }

}

color colour1=color.red; userName name1=userName.Tom / Tom;Int.TryParase(name)=8

结构(struct)是由几个数据组成的数据结构,这些数据可能有不同的类型。根据这个结构,可以定义自己的变量类型。

语法:struct <typeName>{<memberDeclarations>}

数组,在C#中,有3中类型的数组,分别是一维数组、多维数组和交叉数组(C#中的数组和C++中的数组语法机制有很大区别)。数组必须在访问之前初始化。

一维数组声明:<arrayType>[ ] <arrayName>;

数组的初始化有两种方式。1. 以字面形式指定数组的完整内容,eg:int[ ] myArray = {1,2,3,4,5};;2. 指定数组的大小,再使用关键字new初始化所有的数组元素,eg:int[ ] = new int[ 5 ];或 int[ ] myArray = new int [ 5 ] {1,2,3,4,5},后面这种组合方式必须是数组大小和元素个数匹配,并且这里可以将声明与初始化分开代码行完成,即int [ ] myArray;

myArray = new int [ 5 ]。

多维数组声明:<arrayType>[ ,,, ] <arrayName>;

eg:double [ ,] myArray = new double [ 3,4 ];使用字面值初始化的形式是:double [ ,] = {{1,2},{3,4},{5,6}};

交叉数组声明:<arrayType>[ ] [ ] <arrayName>;(声明交叉数组时,其语法要在数组的声明中指定多个方括号对)

交叉数组也有多种声明的语法方式,其中的一种是:将数组的初始化和声明放在同一行上。

eg:int [ ] [ ] myArray = { new int [ ] {1,2,333},new int [ ] {55} , new int [ ] {5,89,33,1000,789}}

C#中的数组是一个变量的下标列表,存储在数组类型的变量中。数组的下标也称数组的索引,索引从0开始,下标是一个整型常量。数组有一个基本类型,数组的条目称为元素,元素都是这种基本类型的变量。

声明数组的方式:<baseType>[] <variableName>。数组必须在访问前进行初始化。初始化有两种方式,可以以字面的形式指定数组的完整内容,也可以指定数组的大小,再使用关键字new初始化所有的数组元素。方式一: int[] myArray = {1,3,5,7,9};(有5个整型元素变量的整型数组)。方式二:int[] myArray = new int[5];(使用关键字new显式地初始化数组,默认每个元素的初始值是0)。【还可以采用两种方式结合的方式声明数组:int[]
myArray[] = new int[5] {1,3,5,7,9},使用这种方式,数组的大小必须与元素的个数相匹配。否则,会出现编译失败】。与其他变量类型一样,不需要在声明的同时进行数组的初始化,这种方式也是合法的:int[] myArray; myArray = new int[5];

多维数组是用多个下标访问其元素的数组。二维数组的声明方式:<baseType>[ , ] <variableName>,多维数组的声明方式:<baseType>[ , , , ] <variableName>。范例如下:

double[3,4] myArray = new double[3,4] 或 double[3,4] myArray = {{1,2,3,4} , {4,6,5,7} ,{1,2,3,4} , {4,6,5,7} } 或 double[ , ] myArray = {,{4,6,5,7} ,{1,2,3,4} , {4,6,5,7} }。多维数组的访问方式:myArray[1,2](可看成第二行,第三列的元素)。

C#中的数组元素的声明时,同样可以使用一个变量来指定该数组的长度,但这个变量必须是声明为const的常变量。另外,也可以使用变长数组。

使用数组中需要注意的:数组是从零开始建立索引,方括号[] 必须跟在数组类型的后面,而不是数组变量的后面(区别于C、C++)。数组的大小不是其类型的一部分(C语言中,数组的大小是数组类型的一部分)。如下:

int[] numbers; // declare numbers as an int array of any size

numbers = new int[10];
// numbers is a 10-element array

numbers = new int[20];
// now it's a 20-element array

C#支持一维数组、多维数组(矩形数组)和数组的数组(交错的数组)。一维数组:int[] myArray; 多维数组: int[ , ] myArray; 数组的数组(交错的): int[] [] myArray;

声明数组并不实际创建它们。在c#中,数组是对象,必须进行实例化。。

一维数组

int[] numbers = new int[5] {1, 2, 3, 4, 5};

string[] names = new string[3] {"Matt", "Joanne", "Robert"};

可省略数组的大小,如下所示:

int[] numbers = new int[] {1, 2, 3, 4, 5};

string[] names = new string[] {"Matt", "Joanne", "Robert"};

如果提供了初始值设定项,则还可以省略 new运算符,如下所示:

int[] numbers = {1, 2, 3, 4, 5};

string[] names = {"Matt", "Joanne", "Robert"};

多维数组

int[,] numbers = new int[3, 2] { {1, 2}, {3, 4}, {5, 6} };

string[,] siblings = new string[2, 2] { {"Mike","Amy"}, {"Mary","Albert"} };

可省略数组的大小,如下所示:

int[,] numbers = new int[,] { {1, 2}, {3, 4}, {5, 6} };

string[,] siblings = new string[,] { {"Mike","Amy"}, {"Mary","Albert"} };

如果提供了初始值设定项,则还可以省略 new运算符,如下所示:

int[,] numbers = { {1, 2}, {3, 4}, {5, 6} };

string[,] siblings = { {"Mike", "Amy"}, {"Mary", "Albert"} };

交错的数组(数组的数组)

可以像下例所示那样初始化交错的数组:

int[][] numbers = new int[2][] { new int[] {2,3,4}, new int[] {5,6,7,8,9} };

可省略第一个数组的大小,如下所示:

int[][] numbers = new int[][] { new int[] {2,3,4}, new int[] {5,6,7,8,9} };

int[][] numbers = { new int[] {2,3,4}, new int[] {5,6,7,8,9} };

请注意,对于交错数组的元素没有初始化语法。

System.Array是所有数组类型的抽象基类型。数组可以使用System.Array具有的属性以及其他类成员(常用的方法就有排序啊,搜索啊和这个数组的复制啊)。

对于数组,使用foreach循环遍历数组。

在C#中,函数是一种方法,可提供在应用程序中任何一处执行的代码块。函数可以是代码的可读性更高,可以用于创建多用途的代码,对不同的数据执行相同的操作。函数Main() 是控制台应用程序的入口点函数。所有的C#可执行代码都必须有一个入口点。通过函数进行数据交换的最简单的方式就是利用返回值。

函数中有返回值的,需要使用return语句来进行值的返回。return语句并不是只能放在函数体的最后一行。函数有返回值的,要求所有的代码块中的代码路径都必须有返回值return语句。return语句同样也可以用在没有返回值的函数中,即函数的返回类型是声明为void的,但不能在关键字return和return语句结束符号——分号之间有返回值,这时return语句的作用是终止函数的执行。

函数中的参数,要求实参和形参完全匹配,即匹配参数的个数,数据类型,参数顺序。

参数数组:C#允许为函数指定一个(只能指定一个)特定的参数,这个参数必须是函数定义中最后一个参数,称为参数数组。参数数组可以使用个数不定的参数调用函数,使用params关键字来定义。参数数组,那么这个参数是一个数组,且数组元素的个数没有限制(0或多个)。

参数数组可以简化代码,因为不必从调用代码中传递数组,而是传递可以函数中使用的一个数组中相同类型的几个参数。

语法范例:

static <returnType> <functionName>(<p1Type> <p1Var>,...., params <type>[ ] <name>){ }

<functionName> (p1,...., <val1>,<val2>,....) (其中,val1,val2的类型是<type>,个数不限)

引用参数和值参数

值参数,是把一个值传递给函数使用的一个变量,对函数中此变量的任何修改都不影响函数调用中指定的参数。调用时,实参和形参使用的是不同内存区域中的值。

引用参数,函数处理的变量和函数调用中使用的变量相同,而不仅仅是值相同的变量,对这个参数变量的任何改变都会影响用作参数变量的值。因为使用引用参数时,实参和形参作用的是同一块内存地址中的内容。

声明引用参数的语法是,在函数的形参添加(最前头)引用参数修饰符ref,,然后在函数调用中,再次使用ref修饰实参指定它是引用参数。eg:static void Show(ref int val);Show(ref val);

用作ref参数的变量有两个限制。范例:

const int val = 5; Show(ref val); // 这是非法的,因为val为const,而其作为ref参数,可能会改变值,显然,就不合法了

int val; Show(ref val); // 像这样的也是不允许的,必须初始化作为ref参数的变量,不能在函数中进行ref参数初始化。

输出参数,使用关键字out,指定所给的参数是一个输出参数,out关键字的使用方式与ref关键字相同,即在函数定义和函数调用中用作参数的修饰符。

实际上,它的执行方式与引用参数完全一样,都是在函数执行完毕后,该参数的值将返回给函数调用中使用的变量。但是,有一些重要区别:把未赋值的变量用作ref参数是非法的,但可以把未赋值的变量用作out参数;另外,在函数使用out参数时,该参数必须看做是还为赋值的,即调用代码可以把已赋值的变量用作out参数,存储在该变量中的值会在函数执行时丢失。

C#中的变量仅能从代码的本地作用域访问,给定的变量有一个作用域,访问该变量呀通过这个作用域来实现。

根据变量的作用域,变量可划分为局部变量和全局变量。

在局部变量和全局变量同名的情况下,必须使用一个完整限定的名称为变量名分类。如果局部变量和全局变量同名,而没有添加相应的名称限定,全局变量就会被屏蔽。

当声明一个简单的变量类型,并不会引起其他的变化(特制内存空间中的存储内容),只有在给变量赋值后,这个值才占用一块内存空间。一般情况下,最好在声明和初始化所有变量后,再在代码块中使用它们,这称为”最佳实践方式“(一个例外是在循环语句for中初始化一个循环变量)。

Main() 函数可以使用如下4中版本:

static void Main()

static void Main(string[] args)

static int
Main()

static
void Main(string[] args)

一般情况下,返回值为0时,表明程序”正常“终止。

结构函数,结构体不仅可以包含数据成员,还可以包含函数成员。

委托是一种可以把引用存储为函数的类型。委托的声明非常类似于函数,但不带函数体,使用delegate关键字来声明一个委托。委托的声明指定了一个返回类型和一个参数列表。在定义了委托后,就可以声明该委托类型的变量。接着把这个变量初始化为与委托有相同返回类型和参数列表的函数引用。之后,就可以使用委托变量调用这个函数,就像该变量是一个函数一样。

在集成开发环境中(VS或VCE),可以用两种方式执行应用程序:调试模式和非调试模式,默认是在调试模式下执行的。

VS和VCE都允许在调试(默认)和发布两种配置下创建应用程序。

PDB 文件

PDB:Program Debug Database(程序调试数据库)文件

程序数据库 (PDB) 文件保存着调试和项目状态信息,使用这些信息可以对程序的调试配置进行增量链接。当用
/ZI 或 /Zi 编译 C/C++ 程序时或用 /debug 编译 Visual Basic/C#/JScript .NET 程序时将创建 PDB 文件。

在 Visual C++ 中,/Fd 选项用于命名由编译器创建的 PDB 文件。当在 Visual Studio 中使用向导创建项目时,/Fd 选项被设置为创建名为 project.PDB 的 PDB 文件。

如果使用生成文件创建 C/C++ 应用程序,并指定 /ZI/Zi 而不指定
/Fd
时,则最终将生成两个 PDB 文件:

VC70.PDB (更笼统地说就是 VCx0.PDB,其中 x 表示 Visual C++ 的版本。)该文件存储各个 OBJ 文件的所有调试信息并与项目生成文件驻留在同一个目录中。
project.PDB 该文件存储 .exe 文件的所有调试信息。对于本机代码,它驻留在 \debug 子目录中。对于托管代码,它驻留在 \WINDEBUG 子目录中。

每当创建 OBJ 文件时,C/C++ 编译器都将调试信息合并到 VCx0.PBD 中。插入的信息包括类型信息,但不包括函数定义等符号信息。因此,即使每个源文件都包含公共头文件(如 <windows.h>),这些头文件中的 typedef 也只存储一次,而不是在每个 OBJ 文件中都存在。

链接器将创建 project.PDB,它包含项目的 EXE 文件的调试信息。project.PDB 包含完整的调试信息(包括函数原型),而不仅仅是 VCx0.PDB 中的类型信息。这两个 PDB 文件都允许增量更新。

Visual Studio 调试器使用由链接器直接创建的 project.PDB 文件并将此 PDB 的绝对路径嵌入到 EXE 或 DLL 文件中。如果调试器在该位置无法找到 PDB 文件或者如果路径无效(例如,如果项目被移动到了另一台计算机上),调试器将搜索包含 EXE 的路径,即在解决方案的“属性页”中指定的“符号路径”(“调试符号文件”页 ->“通用属性”文件夹)。调试器不会加载与所调试的二进制不匹配的 PDB。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: