虽然C#的构想十分接近于传统高级语言C和C++,是一门面向对象的编程语言,但是它与Java非常相似,有许多强大的编程功能,因此得到广大程序员的青睐。下面列出C#一些重要的功能:
在这一章中,我们将讨论创建C#编程所需的工具。我们已经提到C#是.Net框架的一部分,且用于编写.Net应用程序。因此,在讨论运行C#程序的可用工具之前,让我们先了解一下C#与.Net框架之间的关系。
.Net框架是一个创新的平台,能帮您编写出下面类型的应用程序:
.Net框架应用程序是多平台的应用程序。框架的设计方式使它适用于下列各种语言:C#、C++、VisualBasic、Jscript、COBOL等等。所有这些语言可以访问框架,彼此之间也可以互相交互。.Net框架由一个巨大的代码库组成,用于C#等客户端语言。下面列出一些.Net框架的组件:
如需了解每个组件的详细信息,请参阅微软(Microsoft)的文档。
微软(Microsoft)提供了下列用于C#编程的开发工具:
在我们学习C#编程语言的基础构件块之前,让我们先看一下C#的最小的程序结构,以便作为接下来章节的参考。
一个C#程序主要包括以下部分:
C#文件的后缀为.cs。以下创建一个HelloWorld.cs文件,文件包含了可以打印出“HelloWorld”的简单代码:
让我们来看看一个CarApplication(车)类的实现,并借此讨论C#的基本语法:
注释是用于解释代码。编译器会忽略注释的条目。在C#程序中,多行注释以/*开始,并以字符/终止,如下所示:/ThisprogramdemonstratesThebasicsyntaxofC#programmingLanguage*/
单行注释是用'//’符号表示。例如://endclassRectangle
变量是类的属性或数据成员,用于存储数据。在上面的程序中,Rectangle类有两个成员变量,名为length和width。
关键字是C#编译器预定义的保留字。这些关键字不能用作标识符,但是,如果您想使用这些关键字作为标识符,可以在关键字前面加上@字符作为前缀。在C#中,有些关键字在代码的上下文中有特殊的意义,如get和set,这些被称为上下文关键字(contextualkeywords)。
下表列出了C#中的保留关键字(ReservedKeywords)和上下文关键字(ContextualKeywords):
值类型变量可以直接分配给一个值。它们是从类System.ValueType中派生的。
下表列出了C#2010中可用的值类型:
如需得到一个类型或一个变量在特定平台上的准确尺寸,可以使用sizeof方法。表达式sizeof(type)产生以字节为单位存储对象或类型的存储尺寸。下面举例获取任何机器上int类型的存储尺寸:
对象(Object)类型是C#通用类型系统(CommonTypeSystem-CTS)中所有数据类型的终极基类。Object是System.Object类的别名。所以对象(Object)类型可以被分配任何其他类型(值类型、引用类型、预定义类型或用户自定义类型)的值。但是,在分配值之前,需要先进行类型转换。
当一个值类型转换为对象类型时,则被称为装箱;另一方面,当一个对象类型转换为值类型时,则被称为拆箱。objectobj;obj=100;//这是装箱
动态类型与对象类型相似,但是对象类型变量的类型检查是在编译时发生的,而动态类型变量的类型检查是在运行时发生的。
字符串(String)类型允许您给变量分配任何字符串值。字符串(String)类型是System.String类的别名。它是从对象(Object)类型派生的。字符串(String)类型的值可以通过两种形式进行分配:引号和@引号。
类型转换从根本上说是类型铸造,或者说是把数据从一种类型转换为另一种类型。在C#中,类型铸造有两种形式:
下面的实例显示了一个显式的类型转换:
一个变量只不过是一个供程序操作的存储区的名字。在C#中,每个变量都有一个特定的类型,类型决定了变量的内存大小和布局。范围内的值可以存储在内存中,可以对变量进行一系列操作。我们已经讨论了各种数据类型。C#中提供的基本的值类型大致可以分为以下几类:
C#允许定义其他值类型的变量,比如enum,也允许定义引用类型变量,比如class。这些我们将在以后的章节中进行讨论。在本章节中,我们只研究基本变量类型。
C#中变量定义的语法:
在这里,data_type必须是一个有效的C#数据类型,可以是char、int、float、double或其他用户自定义的数据类型。variable_list可以由一个或多个用逗号分隔的标识符名称组成。
一些有效的变量定义如下所示:
inti,j,k;charc,ch;floatf,salary;doubled;
您可以在变量定义时进行初始化:
inti=100;
变量通过在等号后跟一个常量表达式进行初始化(赋值)。初始化的一般形式为:
常量是固定值,程序执行期间不会改变。常量可以是任何基本数据类型,比如整数常量、浮点常量、字符常量或者字符串常量,还有枚举常量。
常量可以被当作常规的变量,只是它们的值在定义后不能被修改。
整数常量可以是十进制、八进制或十六进制的常量。前缀指定基数:0x或0X表示十六进制,0表示八进制,没有前缀则表示十进制。整数常量也可以有后缀,可以是U和L的组合,其中,U和L分别表示unsigned和long。后缀可以是大写或者小写,多个后缀以任意顺序进行组合。
这里有一些整数常量的实例:212/*合法/215u/合法/0xFeeL/合法/078/非法:8不是一个八进制数字/032UU/非法:不能重复后缀*/
以下是各种类型的整数常量的实例:85/*十进制/0213/八进制/0x4b/十六进制/30/int/30u/无符号int/30l/long/30ul/无符号long*/
一个浮点常量是由整数部分、小数点、小数部分和指数部分组成。您可以使用小数形式或者指数形式来表示浮点常量。这里有一些浮点常量的实例:
3.14159/*合法/314159E-5L/合法/510E/非法:不完全指数/210f/非法:没有小数或指数/.e55/非法:缺少整数或小数*/
使用浮点形式表示时,必须包含小数点、指数或同时包含两者。使用指数形式表示时,必须包含整数部分、小数部分或同时包含两者。有符号的指数是用e或E表示的。
字符常量是括在单引号里,例如,'x’,且可存储在一个简单的字符类型变量中。一个字符常量可以是一个普通字符(例如'x’)、一个转义序列(例如'\t’)或者一个通用字符(例如'\u02C0’)。
在C#中有一些特定的字符,当它们的前面带有反斜杠时有特殊的意义,可用于表示换行符(\n)或制表符tab(\t)。在这里,列出一些转义序列码:
字符串常量是括在双引号“”里,或者是括在@''里。字符串常量包含的字符与字符常量相似,可以是:普通字符、转义序列和通用字符使用字符串常量时,可以把一个很长的行拆成多个行,可以使用空格分隔各个部分。这里是一些字符串常量的实例。下面所列的各种形式表示相同的字符串。
算术运算符关系运算符逻辑运算符位运算符赋值运算符其他运算符。
前提:假设如果A=60,且B=13,现在以二进制格式表示,它们如下所示:A=00111100B=00001101
实例:switch(Condition_Value){caseVal01://codingbreak;caseVal02://codingbreak;default://codingbreak;};|
使用运算符来简化if…else语句。
有时候,我们需要多次执行同一块代码。
图解:
循环控制语句更改执行的正常序列。当执行离开一个范围时,所有在该范围中创建的自动对象都会被销毁。
要使用一个方法,您需要:
当调用带有参数的方法时,您需要向方法传递参数。在C#中,有三种向方法传递参数的方式:
单问号用于对int、double、bool等无法直接赋值为null的数据类型进行null的赋值,意思是这个数据类型是Nullable类型的。
inti=3;
等同于:
Nullablei=newNullable(3);
inti;//默认值0intii;//默认值null
双问号用于判断一个变量在为null的时候返回一个指定的值。接下来我们详细说明。
datatype[]arrayName;
datatype用于指定被存储在数组中的元素的类型。[]指定数组的维度。arrayName指定数组的名称。
实例:
**double[]balance=newdouble[10];**double[]balance={2340.0,4523.69,3421.0};int[]marks=newint[5]{99,98,92,97,95};
通过索引(下标)来访问数组元素:
例如:
doublesalary=balance[9];
为了定义一个结构体,您必须使用struct语句。struct语句为程序定义了一个带有多个成员的新的数据类型。
C#中的结构有以下特点:
语法:
enum
其中,
默认情况下,第一个枚举符号的值是0.以此类推。
enumDays{Sun,Mon,tue,Wed,thu,Fri,Sat};
类的定义是以关键字class开始,后跟类的名称。类的主体,包含在一对花括号内。下面是类定义的一般形式:
成员方法(函数)=》实现具体功能的代码
类的构造函数是类的一个特殊的成员函数,当创建类的新对象时执行。构造函数的名称与类的名称完全相同,它没有任何返回类型。
分类:静态变量和静态函数(方法)
调用方式:类名.静态成员名称或类名.静态函数名称
类的析构函数是类的一个特殊的成员函数,当类的对象超出范围时执行。析构函数的名称是在类的名称前加上一个波浪形(~)作为前缀,它不返回值,也不带任何参数。析构函数用于在结束程序(比如关闭文件、释放内存等)之前释放资源。析构函数不能继承或重载。
(仅家族人士有权限或者仅自己和子孙有权限)
abstractclassClass_Name{}
1.方法可以不用实现。(意味着方法体不需要)
2.可以被继承
一个类可以派生自多个类或接口,这意味着它可以从多个基类或接口继承数据和函数。C#中创建派生类的语法如下:
<访问修饰符>class<基类>{…}class<派生类>:<基类>{…}
派生类继承了基类的成员变量和成员方法。因此父类对象应在子类对象创建之前被创建。您可以在成员初始化列表中进行父类的初始化。
多重继承指的是一个类别可以同时从多于一个父类继承行为与特征的功能。与单一继承相对,单一继承指一个类别只可以继承自一个父类。C#不支持多重继承。但是,您可以使用接口来实现多重继承。
—方法重载和重写(归于一章)方法(函数)重载:
多态是同一个行为具有多个不同表现形式或形态的能力。多态性意味着有多重形式。
属性(Property)是类(class)、结构(structure)和接口(interface)的命名(named)成员。
2.抽象类不能直接实例化。
示例:
异常是在程序执行期间出现的问题。C#中的异常是对程序运行时出现的特殊情况的一种响应
文件创建、删除、写入数据、读取数据
List、Dictionary的使用(它们都属于System.Collections.Generic这个命名空间)
泛型(Generic)允许您延迟编写类或方法中的编程元素的数据类型的规范,直到实际在程序中使用它的时候。换句话说,泛型允许您编写一个可以与任何数据类型一起工作的类或方法。
使用泛型是一种增强程序功能的技术,主要体现在以下几个方面:
[attribute(positional_parameters,name_parameter=value,…)]element
.Net框架提供了三种预定义特性:
预定义特性AttributeUsage描述了如何使用一个自定义特性类。它规定了特性可应用到的项目的类型。规定该特性的语法如下:[AttributeUsage(validon,AllowMultiple=allowmultiple,Inherited=inherited)]其中:
这个预定义特性标记了一个条件方法,其执行依赖于指定的预处理标识符。它会引起方法调用的条件编译,取决于指定的值,比如Debug或Trace。例如,当调试代码时显示变量的值。规定该特性的语法如下:[Conditional(conditionalSymbol)]例如:
[Conditional(“DEBUG”)]
这个预定义特性标记了不应被使用的程序实体。它可以让您通知编译器丢弃某个特定的目标元素。例如,当一个新方法被用在一个类中,但是您仍然想要保持类中的旧方法,您可以通过显示一个应该使用新方法,而不是旧方法的消息,来把它标记为obsolete(过时的)。规定该特性的语法如下:[Obsolete(message)][Obsolete(message,iserror)]其中:
反射指程序可以访问、检测和修改它本身状态或行为的一种能力。我们可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型。然后,可以调用类型的方法或访问其字段和属性。
优点:
缺点:
反射(Reflection)有下列用途:
C#中的委托(Delegate)类似于C或C++中函数的指针。委托(Delegate)是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。委托(Delegate)特别用于实现事件和回调方法。
delegate;
类似代理功能,拥有多态性,相同委托可以合并并按顺序执行。
事件(Event)基本上说是一个用户操作,如按键、点击、鼠标移动等等,或者是一些提示信息,如系统生成的通知。应用程序需要在事件发生时响应事件。例如,中断。C#中使用事件机制实现线程间的通信。
//基于上面的委托定义事件publicevent
事件具有以下属性:
线程生命周期开始于System.Threading.Thread类的对象被创建时,结束于线程被终止或完成执行时。下面列出了线程生命周期中的各种状态: