多语言企业网站建设,自动seo优化,番禺 大石网站建设,如何创建网站本篇内容参考C#图解教程
本篇内容偏向基础#xff0c;适合0基础的朋友快速上手#xff0c;也适合有一定C语言#xff08;或其他语言如C,java#xff09;基础的人快速上手C#。同时适合unity引擎的初学者#xff0c;更加详细的了解C#语言。
本文内容基本涵盖C#基础内容适合0基础的朋友快速上手也适合有一定C语言或其他语言如C,java基础的人快速上手C#。同时适合unity引擎的初学者更加详细的了解C#语言。
本文内容基本涵盖C#基础内容对于接口事件等会给出学习资料但文章中不涉及。
1.C#程序的概述
1.1一个简单的C#程序
using System;
namespace HelloWorld
{class Program{static void Main(string[] args){Console.WriteLine(Hello World!);}}
}运行结果 Image 一个简单的C#程序由一下部分组成
1using命令行如行1告诉程序使用System这个命名空间的类型
2声明当前程序内容的命名空间
3在命名空间中声明程序所需的类与C的类相似
4写出Main方法程序由Main方法的开头开始执行直到Main方法结束程序结束
1.2标识符
标识符是一种字符串可以用来命名变量、方法、参数
标识符字符串的规则
1字母和下划线可以出现在标识符的任何位置
2数字不可以放在首位
3字符只能出现在标识符的首位
1.3关键字
同C/C一样不可以将变量、方法、参数命名成关键字 如下是C#的关键字表
1.4空白
程序中的空白指的是没有可视化输出的字符程序员在代码中使用空白将被编译器忽略但他可以使代码更加清晰易懂。
空白字符包括空格制表符tab换行符、回车符
1.5语句
C#的语句与CJAVA等相似相信绝大多数人并不是0基础来看C#知识的这部分就跳过。
1.6从程序中输出文本
在C#学习的过程中免不了调试代码为了可以更加清晰的显示数据我们需要对变量进行输出所以给出在Console的类该类包含了输入到输出到控制台窗口的方法。
Write与WriteLine 使用方法形如
System.Console.Write(“ ”);
System.Console.WriteLine(“ ”);
1.6.2代码WriteLine的使用
using System;
class Program{static void Main(){int a 5;int b 10;Console.WriteLine(a {0},b {1}, a, b);}
}Console.WriteLine的括号中一共有三个参数第一个参数和普通的输出字符串类似只是加入了”{int}”这样的标记例如”{0}”的意思就是在这个标记所在处插入Console.WriteLine的括号中的第一个参数”{1}”的意思就是在这个标记处插入Console.WriteLine的括号中的第二个参数。第二个参数是用来控制输出的字符占多少位类似C中的setfill()函数、第三个参数是是数字格式说明符。
以下是标准数字格式说明符 Image Write与WriteLine的不同
Write在输出不换行
WriteLine输出后换行
1.7为代码添加注释
C#中单行注释 // 与带分隔符号 / / 的注释用法与C/C一致。
2.类的基本概念
在第二章开始前提一嘴在C#的变量类型与C基本一致所以不过多赘述只给出一些定义 C# 中存在一系列基本数据类型它们包含整数、浮点数、布尔值即逻辑值只能是真或假、字符、字符串。
1C# 中使用类型变量名; 语句声明一个变量。变量遵循先声明后使用的原则。要使用一个变量必须先在前面声明它。
2C# 中使用变量名 值; 语句为变量赋值。赋值语句的意思是在计算出值后将变量名代表的变量修改为这个值。
3C#中使用类型变量名 值; 语句声明一个变量同时给这个变量赋值。
4对变量的首次赋值称为赋初值。C# 中遵循先赋初值后使用的原则。要将变量用于除赋值外的用途必须保证这个变量已经被赋初值。在C#中没有想C一样的
5C#中使用 ((类型)值) 表达式将值转换为指定类型。这与 C 中 C 风格的类型转换语法相同。在语法上 C# 只支持这一种转换方式意即C# 不支持 C 中 类型(值) 这样的类型转换。
6C#中支持一些 C 中不支持的隐式类型转换。String 加上 long时会首先隐式转换为 string而两个字符串相加意味着字符串的连接。 Image 2.1类的概述
类是一种活动的数据结构其有三大属性封装继承多态
类有数据成员函数成员组成。
数据成员用于存储数据由字段相当于C/C的变量常量组成
函数成员用于执行代码方法相当于C/C的函数属性运算符析构函数构造函数索引器事件
2.2声明类
类的声明定义新的类的特征和成员与创建类的实例但创建实例的模板。类的声明提供下列内容类的声明类的特征类的成员。
Class Student{//关键字 类名//类的成员声明
}2.3创建类的实例
声明类只是说明了类的数据成员与函数成员而并不会实际的开辟空间来存储。想要创建一个类并为实际的数据分配内存需要用到以下三点。
1.使用关键字new
2.要分配内存的实例的类型名称
3.使用一对圆括号圆括号中可能有参数也可能没有参数这取决于构造函数
形如
类名 变量名 new 类名();
var 变量名 new 类名();或
类名 变量名
变量名 new 类名()2.3类中的访问修饰符
2.3.1类中的访问修饰符的概述 访问修饰符一般出现在类中成员声明之前 语法
字段
访问修饰符 类型 标识符
方法
访问修饰符 返回类型 方法名( )
访问修饰符一共五种包括 (private) (public) (protected) (internal) (protected internal)
在本文中只介绍前两种剩余的留到C#继承中讲解。
2.3.2private(私有访问)与public(公有访问)
2.3.2.1 private 访问修饰符
私有成员只能从声明它的类的内部访问其他的类看不见或无法访问它们。
私有访问是默认的访问级别、所以如果一个成员在声明时不带访问修饰符那它就是私有成员。还可以使用private访问修饰符显式地将一个成员声明为私有。隐式地声明私有成员和显式地声明在语义上没有不同两种形式是等价的。
例如下面的两个声明都指定了private int成员
int MyInt1; //隐式声明为私有
private int MyInt2; //显式声明为私有
2.3.2.2 public访问修饰符
实例的公有成员可以被程序中的其他对象访问。必须使用public访问修饰符指定公有访问。
形如public int MyInt;
类C1声明了公有和私有的字段和方法
class C1
{int F1; //隐式私有字段private int F2; //显式私有字段public int F3; //公有字段void DoCalc() //隐式私有方法{……}public int GetVal() //公有方法{……}
{Image 2.4从类的内部访问成员
类的成员仅用其他类成员的名称就可以访问它们。
例如下面的类声明展示了类的方法对字段和其他方法的访问。即使字段和两个方法被为private类的所有成员还是可以被类的任何方法(或任何函数成员)访问。
class DaysTemp
{//字段private int High75;private int Low45;//方法private int Get High(){return High;//访问私有字段}private int Get Low(){return Low;//访问私有字段}public float Average(){return (GetHigh() GetLow()) / 2;}
}2.5从类的外部访问成员
要从类的外部访问实例成员必须包括变量名称和成员名称中间用句点(.)分隔。这称为点运算符后文会详细讨论。
例如下面代码的第二行展示了一个从类的外部访问方法的示例
DaysTempmyDt new DaysTemp();//创建类的对象
float fValuemyDt. Average();//从外部访问
DaysTemp内的两个字段被声明为public所以可以从类的外部访问它们。
方法Main是类Program的成员。它创建了一个变量和类DaysTemp的对象并给对象的字段赋值。然后它读取字段的值并打印出来。
class DaysTemp//声明类DaysTemp
{public int High75;public int Low45;
}
class Program//声明类Program
{static void Main(){DaysTemp tempnew DaysTemp(); //创建对象temp.High85;//字段赋值temp.Low 60;Console.WriteLine(“High: {0}”,temp.High);Console.WriteLine($”Low: {temp.Low}”);}
}3.方法
3.1方法的结构本章内容如果是有C/C基础的人可以粗略跳过,方法就相当于C中的函数
方法是一块具有名称的代码。可以使用方法的名称从别的地方执行代码也可以把数据方法并接收数据输出。
方法主要有两个部分方法头与方法体
方法头指定方法的特征包括
1方法是否返回数据如果返回返回什么类型
2方法的名称
3哪种类型的数据可以传递给方法或从方法返回以及如何应对处理这些数据
方法体包含可执行代码的语句序列执行过程从方法体的第一条语句一直到整个方法结束。
3.2局部变量与局部常量
局部变量
局部变量也保存数据。字段通常保存和对象状态有关的数据而建局部变量经常是用于保存
局部的或临时的计算数据。
形如变量类型 变量名称 可选的初始化语句想同类型的变量或者值;
1局部变量的存在和生存期仅限于创建它的块及其内嵌的块。
2从声明它的那一点开始存在在块完成执行时结束存在。
3可以在方法体内任意位置声明局部变量但必须在使用它们前声明。
局部常量
局部常量很像局部变量只是一旦被初始化它的值就不能改变了。如同局部变量局部瘤量必须声明在块的内部。
形如关键字const 变量类型 变量名称 必须进行初始化;
1在声明时必须初始化。
2在声明后不能改变。
相信大部分人有一定的编程基础所以下内容跳过与C/C基本一致就不多赘述了
3.3方法的调用 跟(C/C)一样使用方法名称并带上与之对应的方法列表。
3.4返回值
3.5返回语句与void方法
3.6形参与实参
3.7局部函数从C#7.0开始添加的新标准
方法块内的代码可以调用另一个方法。如果另一个方法在同一个类内可以直接使用它的名称并传入所需的参数(参见下一节)进行调用。如果另一个方法在不同的类中、必须通过这个类的一个对象实例调用它。另一个类中的方法必须使用 public访问修饰符声明。、
从C#7.0开始你可以在一个方法中声明另一个单独的方法。这样可以将嵌入的方法跟其他代码隔离开来、所以它只能在包含它的方法内调用。如果使用恰当这可以使代码更清晰更于维护。这些嵌入的方法被称为局部函数。 与局部变量必须在使用之前进行声明不同你可以在包含方法的任意位置声明局部函数。下面的代码演示了一个 MethodWithlocalFunction 方法它包含了一个局部函数。
class Program
{public void MethodWithLocalFunction (){int MyLocalFunction (int zì)//声明局部函数{return z1*5;}int results MyLocalFunction 5//调用局部函数Console. Writeline($Results of local function call:{results}\\);}static void Main(string[]args){Program myProgramnew Program();myProgram. MethodWithLocalFunction ();//调用方法}
}3.8引用参数这跟C中的引用几乎一致
使用方法
1使用引用参数时必须在方法的声明和调用中都使用ref修饰符。
2实参必须是变量在用作实参前必须被赋值。如果是引用类型变量可以赋值为一个用或null。
引用参数的特征
1不会在栈上为形参分配内存。
2形参的参数名将作为实参变量的别名指向相同的内存位置。
注由于形参名和实参名指向相同的内存位置所以在方法的执行过程中对形参体方法完成后依然可见(表现在实参变量上)。记住要在方法的声明和调用上都使用ref关键字。
引用使用展示
using System;
class Program{static void Main(){int a5;ref int b ref a;Console.WriteLine($a {a},b {b});b 10;Console.WriteLine($a {a},b {b});}
}运行结果 Image 引用作为方法参数代码展示这与C引用几乎一致就不详细解释了
using System;class Method{publicvoid swap(ref int x,ref int y){int tempx;x y;y temp;}}class Program{static void Main(){Method way new Method();int a 5;int b 10;Console.WriteLine(a {0},b {1}, a, b);Console.WriteLine(after swap value);way.swap(ref a,ref b);Console.WriteLine(a {0},b {1}, a, b);}
}运行结果 Image ref局部变量与ref返回
别名功能3.8第一个代码不是ref局部变量功能最常见的用途。实际上它经常和ref返回功能一般用。ref返回功能提供了一种使方法返回变量引用而不是变量值的方法。这里需要的额外语法使用了ref关键字两次一次是在方法的返回类型声明之前另一次是在return关键字之后被返回对象的变量名之前
代码展示
using System;class Score{private int score;public void display(){Console.WriteLine($score {score});}public ref int get_s(){return ref score;}public void s(){this.score 5;}}class Program{static void Main(){Score s1 new Score();s1.s();s1.display();ref int r_score ref s1.get_s();r_score 10;s1.display();}
}说明我们在此程序中运用ref返回在类外通过修改r_score的值按C理解方式此时r_score与s1中score有相同的地址
运行结果 Image 3.9输出参数在实际使用中比较少
输出参数用于从方法体内把数据传出到调用代码它们的行为与引用参数类似。如同引用参数输出参数有以下要求。
1必须在声明和调用中都使用修饰符。输出参数的修饰符是out而不是ref。
2和引用参数相似实参必须是变量而不能是其他类型的表达式。这是有道理的因为方法需要内存位置来保存返回值。
与引用参数类似输出参数的形参充当实参的别名。形参和实参都是同一块内存位置的名称。显然在方法内对形参做的任何改变在方法执行完成之后(通过实参变量)都是可见的。
与引用参数不同输出参数有以下要求。
1在方法内部、给输出参数赋值之后才能读取它。这意味着参数的初始值是无关的而且没有必要在方法调用之前为实参赋值。
2在方法内部在方法返回之前代码中每条可能的路径都必须为所有输出参数赋值。
因为方法内的代码在读取输出参数之前必须对其写人所以不可能使用输出参数把数据传入方法。事实上如果方法中有任何执行路径试图在方法给输出参数赋值之前读取它的值编译器就会产生一条错误消息。
3.10参数数组
3.10.1参数数组概述
在之前的描述中一个形参必须严格地对应一个实参。参数数组则不同它允许特定类型的零个或多个实参对应一个特定的形参。参数数组的重点如下。
1在一个参数列表中只能有一个参数数组。
2如果有参数数组它必须是列表中的最后一个。
3由参数数组表示的所有参数必须是同一类型。
声明一个参数数组时必须做的事如下。 1在数据类型前使用params修饰符。 2在数据类型后放置一组空的方括号。
形如
//方法返回类型 方法名称(修饰符 变量类型[ ] 参数名称)
Int sum( params int[ ] arrry) {……
}类型名后面的空方括号指明了参数是一个整数数组。在这里不必在意数组的细节它们将在后面详细阐述。而现在你需要了解的内容如下。
1数组是一组有序的同一类型的数据项。
2数组使用一个数字索引进行访问。
3数组是一个引用类型因此它的所有数据项都保存在堆中。
3.10.2 方法调用
可以使用两种方式为参数数组提供实参。
1一个用逗号分隔的该数据类型元素的列表。所有元素必须是方法声明中指定的
ListInts(10, 20, 30);//3个int
2一个该数据类型元素的一维数组。
int [] intArray {1,2,3};
ListInts(intArray);//一个数组变量
注在这些示例中没有在调用时使用params修饰符。参数数组中修饰符他参数类型的模式并不相符。
params修饰符的用法总结如下。 1在声明中需要修饰符。 2在调用中不允许有修饰符。
3.11方法重载与C中的函数重载基本一致就不再详细赘述
一个类中可以有多个同名方法这叫作方法重载。使用相同名称的每个方法必须有一个和其他方法不同的签名。
1方法的名称
2参数的数目
3参数的数据类型和顺序
4参数修饰符。
注返回类型不是签名的一部分而我们往往误认为它是签名的一部分。形参的名称也不是签名的一部分。
3.12命名参数与可选参数
命名参数是真的不想说我感觉在实际的开发过程中没有人回去用先挖个坑万一以后真的有需要再来补上
可选参数跟构造函数中的参数默认值很像
所谓可选参数就是可以在调用方法的时候包含这个参数也可以省略它。
为了表明某个参数是可选的你需要在方法声明中为该参数提供默认值。指定默认值的语法和初始化局部变量的语法一样如下面代码的方法声明所示。
形参b的默认值设置成3因此、如果在调用方法的时候只有一个参数方法会使用3作为第二个参数的初始值。
class MyClass
{public int Cale(int a, int 3){return ab; }static void Main(){MyClass me new MyClass();int r0 mc. Calc(5,6);//使用显式值int r1 mc. Calc(5);//为b使用默认值Console.WriteLine(${r0},{r1});}
}这段代码产生如下输出 11,8
对于可选参数的声明我们需要知道如下几个重要事项。
1不是所有的参数类型都可以作为可选参数。
2只要值类型的默认值在编译的时候可以确定就可以使用值类型作为可选参数。只有在默认值是null的时候引用类型才可以用作可选参数。
3.13递归
略……
4.深入理解类
4,1成员修饰符的顺序
在前面的内容中你看到字段和方法的声明可以包括如public和private这样的修饰符。
类成员声明语句由下列部分组成核心声明、一组可选的修饰符和一组可选的特性(attribute用于描述这个结构的语法如下。方括号表示方括号内的成分是可选的。
[特性] [修饰符] 核心声明
可选成分如下。
修饰符
1如果有修饰符必须放在核心声明之前。
2如果有多个修饰符可以任意顺序排列。
特性
1如果有特性必须放在修饰符和核心声明之前。
2如果有多个特性可以任意顺序排列。
至此只解释了两个修饰符即public和private。以后会介绍特性。例如public static都是修饰符可以一起修饰某个声明。因为它们都是修饰符所以可以任何顺序放置。两行代码在语义上是等价的
public static int MaxVal;
static public int MaxVal;
4.2静态字段
静态字段被类的所有实例共享所有实例都访问同一内存位置。因此如果该内存位置的值被一个实例改变了这种改变对所有的实例都可见。
可以使用static修饰符将字段声明为静态如
class D
{int Mem1; //实例字段static int Mem 2; //静态字段
}例如上面代码声明了类D它含有静态字段Mem2和实例字段Mem1。Main定义类D的两个实例。静态成员Mem 2是与所有实例分开保存的。并且从实例内部访问或更新静态字段的语法和访问或更新其他成员字段一样。
因为Mem2是静态的所以类D的两个实例共享一个Mem2字段。如果Meme2被改变了个改变在两个实例中都能看到。成员Mem 1没有声明为static所以每个实例都有自己的副本。
4.3 从类的外部访问静态成员
方法一
就像实例成员静态成员也可以使用点运算符从类的外面进行访问但因为没有实例所以访问静态成员的方法使用类名 形如
class D {static int Mem;
……
}
D.Mem Value; //访问静态成员代码
using System;class A{public const int N 10010;public static void display(){Console.WriteLine($N {N});}}class Program{static void Main(){Console.WriteLine($A.N {A.N});A.display();}
}运行结果 Image 方法二
使用using static声明在该成员所属的类中包含一个using static声明。 样例如下
using static System.Console;
…………
WriteLine(“$hello world”);
静态成员的生存周期静态成员的生命期与实例成员的不同
只有在实例创建之后才产生实例成员在实例销毁之后实例成员也就不存在了。但是即使类没有实例也存在静态成员并且可以访问。
4.4静态函数成员
1如同静态字段静态函数成员独立于任何类实例。即使没有类的实例仍然可以调态方法。
2静态函数成员不能访问实例成员但能访问其他静态成员。 访问静态函数的方法与访问静态字段一致。
4.5其他静态类成员类型
方法√ 属性√ 构造函数√ 运算符√ 索引器× 事件√ 字段√ 类型√ 常量×
4.6成员常量
特别说明与C和C不同在C#中没有全局常量。每个常量都必须声明在类型内。
成员常量类似前一章所述的局部常量只是它们被声明在类声明中而不是方法 内如下面的示例
class MyClass
{const int IntVal100;//定义int类型常量
}
const double PI3.1416;//错误不能在类型声明之外声明成员常量与前面讲的局部常量几乎一致不过是声明在类中。
4.7属性
4.7.1属性概述
属性是代表类实例或类中的数据项的成员。使用属性就像写入或读取一个字段语法相同。
属性的特征
1属性是命名的类成员。
2属性有类型。
3属性可以被赋值和读取。
4属性不一定为数据存储分配内存!
5属性会执行代码。
属性是一组(两个)匹配的、命名的、称为访问器的方法。
1set访问器为属性赋值。
2get访问器从属性获取值。
4.7.2属性声明和访问器
set和get访问器有预定义的语法和语义。可以把set访问器想象成一个方法带有理参数它“设置”属性的值。get访问器没有参数并从属性返回一个值。
set访问器
1拥有一个单独的、隐式的值参名称为value与属性的类型相同
2拥有一个返回类型void。
get访问器
1没有参数
2拥有一个与属性类型相同的返回类型
形如
Set与get说明
set访问器中的隐式参数value是一个普通的值参。和其他值参一样可以用它发送双数据到方法体或访问器块。在块的内部可以像普通变量那样使用value包括对它赋值。
get访问器的所有执行路径必须包含一条return语句它返回一个属性类型的值。
访问器set和get可以以任何顺序声明并且除了这两个访问器外属性上不允许有其他方法
4.7.3属性的示例
下面的代码展示了一个名为C1的类的声明示例它含有一个名为MyValue的属性。
请注意属性本身没有任何存储。取而代之访问器决定如何处理发送进来的数据以及应将什么数据发送出去。
在代码之前在介绍一下如何使用属性
要写入一个属性在赋值语句的左边使用属性的名称。
要读取一个属性把属性的名称用在表达式中。
例如下面的代码包含一个名为MyValue的属性的声明。只需使用属性名就可以写入和读取属性就好像它是一个字段名。
int MyValue//属性声明
{set{ ...}get{…‥}
}MyValue 5;//赋值 隐式调用set方法
z MyValue;//表达式 隐式调用get方法
属性会根据是写入还是读取来隐式地调用适当的访问器。不能显式地调用访问器因为这样做会产生编译错误。
y MyValue. get();//错误!不能显式调用get访问器
MyValue. set(5);//错误不能显式调用set访问器
代码如下
using System;
class C1{private int m_value 10;pubilc int Myvalue //属性不分配内存{set { m_value value; }get { return m_value}}}class Program{static void Main(){C1 c new C1();Console.WriteLine(Myvalue: {0}, c.Myvalue);c.Myvalue 20;Console.WriteLine(Myvalue: {0}, c.Myvalue);}
}运行结果 Image C#7.0为属性的getter/setter引入了另一种语法(lambma表达式)这种语法使用表达函数体。这种语法只有在访问函数体由一个表达式组成的时候才能使用。以后再详细介绍
int MyValue
{
setvalue100? 100: value;
get theRealValue ;
}4.7.4只读和只写属性
要想不定义属性的某个访问器可以忽略该访问器的声明。
1只有get访问器的属性称为只读属性。只读属性能够安全地将一个数据项从类或类的实例中传出而不必让调用者修改属性值。
2只有set访问器的属性称为只写属性。只写属性很少见因为它们几乎没有实际用途。如果想在赋值时触发一个副作用应 该使用方法而不是属性。
3两个访问器中至少有一个必须定义否则编译器会产生一条错误消息。
4.7.5属性是用来替代公有字段的方法之一
属性比公有字段更好理由如下。
1属性是函数成员而不是数据成员允许你处理输入和输出而公有字段不行。
2属性可以只读或只写而字段不行。
3编译后的变量和编译后的属性语义不同。
4.7.6自动属性 这里留一个坑以后再填
4.7.7静态属性
属性也可以声明为static。静态属性的访问器和所有静态成员一样具有以下特点。
1不能访问类的实例成员但能被实例成员访问。
2不管类是否有实例它们都是存在的。
3在类的内部可以仅使用名称来引用静态属性。
4在类的外部正如前面描述的可以通过类名或者使用using static结构来引用静态属性。
例如下面的代码展示了一个类它带有名为MyVa1ue的自动实现的静态属性。在Main的头三行即使没有类的实例也能访问属性。Main的最后一行调用一个实例方法它从类的内部访问属性。
代码展示
using System;
using static ConsoleTestApp.Trivial;
namespace ConsoleTestApp
{class Trivial{public static int MyValue { get; set; }public void PrintValue(){ Console.WriteLine(Value from inside:{0}, MyValue); }}class Program{static void Main(){Console.WriteLine(Init Value:{0}, Trivial.MyValue);Trivial.MyValue 10;Console.WriteLine(New Value:{O}, Trivial.MyValue);MyValue 20;//从类的外部访问但由于使用了using static所以没有使用Console.WriteLine($New Value:{MyValue});Trivial tr new Trivial();tr.PrintValue();}}
}4.8构造函数
跟C的构造函数基本一致所以接下来就直接给出代码就不详细讲解
代码
using System;class Student{string m_name;int m_id;public Student(){m_name NO Student;m_id 0;}public Student(string name, int id){m_name name;m_id id;}public void display(){Console.WriteLine($Name: {m_name} Id: {m_id});}}class Program{static void Main(){Student a new Student();Student b new Student(Lijiaqin, 218228);a.display();b.display();}
}代码using System;class Student{string m_name;int m_id;public static int number;public static void fir(){number 1;}public Student(){m_name NO Student;m_id 0;number;}public Student(string name, int id){m_name name;m_id id;number; }public void display(){Console.WriteLine($Name: {m_name} Id: {m_id} Number: {number});}}class Program{static void Main(){Student.fir();Student a new Student();a.display();Student b new Student(Lijiaqin, 218228); b.display();}
}4.9析构函数
C#有自己的垃圾回收机制不需要为类写出析构函数
4.10 readonly修饰符
字段可以用readonly修饰符声明。其作用类似于将字段声明为const一旦值被设定就不能改变。
1const字段只能在字段的声明语句中初始化而readonly字段可以在下列任意位置设置它的值。
2const字段的值必须可在编译时决定而readonly字段的值可以在运行时决定。这种自由性允许你在不同的环境或不同的构造函数中设置不同的值。
3它可以是实例字段也可以是静态字段它在内存中有存储位置。
4.11 this关键字
this关键字在类中使用是对当前实例的引用。它只能被用在下列类成员的代码块中。
1实例构造函数。
2实例方法
3属性和索引器的实例访问器(索引器将在下一节阐述)。
注因为静态成员不是实例的一部分所以不能在任何静态函数成员的代码中使用this关键字。更适当地说this用于下列目的
1用于区分类的成员和局部变量或参数
2作为调用方法的实参。
例如下面的代码声明了类MyClass它有一个int字段和一个方法方法带有一个单独的int参数。方法比较参数和字段的值并返回其中较大的值。唯一的问题是字段和形参的名称相同都是var1。在方法内使用this关键字引用字段以区分这两个名称。
class MyClass
{int var1 10;public int ReturnMaxSum ( int var1){Return var1 this.var1 ? var1 : this.var1; //var1是参数this.var1是字段}
}4.12 索引器
4.12.1索引器的引入 Image 4.12.2索引器的声明
声明索引器的语法如下所示。请注意以下几点。
1索引器没有名称。在名称的位置是关键字this。
2参数列表在方括号中间。
3参数列表中必须至少声明一个参数。
形如
ReturnType this(关键字)[Type param 1 , ……](参数列表){get {……}Set{……}
}4.12.3索引器和属性的对比
索引器和属性在很多方面是相似的。
1和属性一样索引器不用分配内存来存储。
2索引器和属性都主要被用来访问其他数据成员它们与这些成员关联并为它们提供取和设置访问。属性通常表示单个数据成员。索引器通常表示多个数据成员。 说明可以认为索引器是为类的多个数据成员提供get和set访问的属性。通过提供索引器可以在许多可能的数据成员中进行选择。索引本身可以是任何类型而不仅仅是数值类型。 关于索引器还有一些注意事项如下。
1和属性一样索引器可以只有一个访问器也可以两个都有。
2索引器总是实例成员因此不能被声明为static。
3和属性一样实现get和set访问器的代码不一定要关联到某个字段或属性。这段代码可以做任何事情也可以什么都不做只要get访问器返回某个指定类型的值即可。
4.12.4索引的set 与get访问器
set
当索引器被用于赋值时set访问器被调用并接受两项数据如下
1一个名为value的隐式参数其中持有要保存的数据
2一个或更多索引参数表示数据应该保存到哪里。
形如emp[0]Doe;
set访问器有如下语义 1它的返回类型为void。 2它使用的参数列表和索引器声明中的相同。 3它有一个名为value的隐式参数值参类型和索引器类型相同。
get
当使用索引器获取值时可以通过一个或多个索引参数调用get访问器。索引参数指示获取哪个值。 形如
string semp[0];
get访问器方法体内的代码必须检查索引参数确定它表示的是哪个字段如果get是以普通方法的语法书写的。get访问器有如下语义。 1它的参数列表和索引器声明中的相同。 2它返回与索引器类型相同的值。
4.12.5代码展示
下面的代码为先前示例中的类Employee声明了一个索引器。
1索引器需要读写string类型的值所以string必须声明为索引器的类型。它必须声明为public以便从类的外部访问。2个字段被随意地索引为整数0-2所以本例中方括号中间名为index的形参必须为int型。在set访问器方法体内代码确定索引指的是哪个字段并把隐式变量value的值赋给它。3在get访问器方法体内代码确定索引指的是哪个字段并返回该字段的值。
代码1
class Employee
{public string LastName;//调用字段0public string FirstName;//调用字段1public string CityOfBirth ;//调用字段2public string this[int index]//索引器声明{set//set访问器声明{switch(index) {case 0: LastName value;break;case 1: FirstName value;break;case 2: CityOfBirth value;break;default://(异常以后再聊)throw new ArgumentOutOfRangeException (index);}}get//get访问器声明{switch(index){case 0: return LastName;case 1: return FirstName;case 2: return CityOfBirth ;default://(异常)throw new ArgumentOutOfRangeException (index);}}}
}代码2
class Class 1
{int Tempo;//私有字段int Tempi;//私有字段public int this[int index]//索引{get{return(0index? Temp0:Temp 1;)//返回Tempo或Tempi的值}set{if (0 index)Temp0value;//注意隐式变量valueelseTempivalue;//注意隐式变量value}}
}
class Example
{static void Main(){Class1 anew Class1();Console. Writeline(Values--TO:{0},T1:{1},a[0],a[1]);a[0]15;a[1]20;Console.WriteLine($Values--TO:{a[O]},T1:{a[1]});}}
}
代码运行结果Values -- T0: 0, T1:0;Values -- T0: 15, T20;