第一篇:C#作业参考答案
语句while(x>10 && x<100);在10 对 错 题目2 答案已保存 满分1.00 Flag question 题干 执行程序段 int count=0;while(count<=7);Console.WriteLine(count);的输出结果是()。选择一项: a.4 b.2 c.死循环 d.3 题目3 答案已保存 满分1.00 Flag question 题干 对于语句“if(表达式)语句块”,下列说法正确的是()选择一项: a.语句中的“表达式”可以是任意类型的表达式 b.不管“表达式”的形式如何,但其返回值必须是布尔类型,如果返回true则执行后面的语句块,否则不执行 c.语句中的“表达式”可以是整型表达式或者布尔表达式 d.如果“表达式”的值为非零值则执行后面的语句块,为零则不执行 题目4 答案已保存 满分1.00 Flag question 题干 下面赋值正确的是()。选择一项: a.float fNum=1.5;b.char ch=“a”;c.double dNum=1.34;d.string str=’good’; 题目5 答案已保存 满分1.00 Flag question 题干 下面正确的字符常量是()。选择一项: a.'“' b.'” c.“c” d.'K' 题目6 答案已保存 满分1.00 Flag question 题干 在程序执行时,注释使得//后面的文本打印在屏幕上 选择一项: 对 错 题目7 答案已保存 满分1.00 Flag question 题干 现有如下程序 using system;class Example1 { public static voidMain(){ int x=1,a=0,b=0;switch(x){ case 0:b++;break;case 1:a++;break;case 2:a++;b++;break;} Console.WriteLine(“a={0},b={1}”,a,b);} } 当程序运行时,其输出结果是()。选择一项: a.a=2,b=1 b.a=2,b=2 c.a=1,b=0 d.a=1,b=1 题目8 答案已保存 满分1.00 Flag question 题干 与Java一样,Visual Studio.NET也具有跨平台的特性,其原因在于它引入Java的 JVM。选择一项: 对 错 题目9 答案已保存 满分1.00 Flag question 题干 为了将字符串str=“123,456”转换成整数123456,应该使用以下哪条语句?()选择一项: a.int Num = int.Parse(str);b.int Num = int.Parse(str,System.Globalization.NumberStyles.AllowThousands);c.int Num = str.Parse(int);d.int Num =(int)str;题目10 答案已保存 满分1.00 Flag question 题干 String类Trim方法可以删除字符串开始和结尾的所有空格 选择一项: 对 错 题目11 答案已保存 满分1.00 Flag question 题干 公共语言运行库(CLR)要求程序员管理他们自己的内存 选择一项: 对 错 题目12 答案已保存 满分1.00 Flag question 题干 计算机可以直接执行机器语言、但汇编语言和高级程序设计语言需要编译成机器语言后才能被执行。选择一项: 对 错 题目13 答案已保存 满分1.00 Flag question 题干 变量类型float可以被提升为double型 选择一项: 对 错 题目14 答案已保存 满分1.00 Flag question 题干 下列数据类型中,不属于基本数据类型的是()。选择一项: a.字符类型和字符串类型 b.数值类型 c.布尔类型和对象类型 d.结构类型 题目15 答案已保存 满分1.00 Flag question 题干 解决方案资源管理器窗口的功能是()。选择一项: a.显示指定对象的属性 b.编写程序代码 c.提供常用的数据控件、组件、Windows窗体控件等 d.显示一个应用程序中所有的属性以及组成该应用程序的所有文件 题目16 答案已保存 满分1.00 Flag question 题干 已定义下列变量:int n;float f;double df;df=10;n=2;下列语句正确的是()选择一项: a.n=df b.f=12.3 c.df=n=100;d.f=df 题目17 答案已保存 满分2.50 Flag question 题干 C#源程序文件的扩展名是()。选择一项: a..vb b..c c..cs d..cpp 题目18 答案已保存 满分1.00 Flag question 题干 一个数组同时可以存储很多不同类型的值 选择一项: 对 错 题目19 答案已保存 满分1.00 Flag question 题干 面向对象程序设计方法虽然是一种主流的设计方法,但类中成员函数的设计仍然离不开结构化程序设计方法。选择一项: 对 错 题目20 答案已保存 满分1.00 Flag question 题干 项目文件的扩展名是()。选择一项: a.csproj b.sln c.proj d.cs 以下装箱、拆箱语句中,错误的有()。选择一项: a.object obj=100;int m= obj;b.object obj=100;int m=(int)obj;c.object obj=(object)100;int m=(int)obj;d.object obj=(int)100;int m=(int)obj;题目22 答案已保存 满分1.00 Flag question 题干 无论使用那种.NET语言,MSIL是所有的.NET程序所编译成的通用中间格式 选择一项: 对 错 题目23 答案已保存 满分1.00 Flag question 题干 下面关于命名空间的说法,错误的是()。选择一项: a.使用命名空间的好处是,不但在不同命名空间中的成员可以重名,而且在同一个命名空间中的成员也可以重名 b.C#中,命名空间可有可无,看需要来定义和使用 c.同一个命名空间中的成员不能重名,不同命名空间中的成员可以重名 d.命名空间为程序的逻辑结构提供了一种良好的组织方法 题目24 答案已保存 满分1.00 Flag question 题干 String类方法ToUpper只将字符串的首写字母大写 选择一项: 对 错 题目25 答案已保存 满分1.00 Flag question 题干 所有的变量在声明它们的时候必须给出数据类型 选择一项: 对 错 题目26 答案已保存 满分1.00 Flag question 题干 C#认为变量number和NuMbEr是等效的 选择一项: 对 错 题目27 答案已保存 满分1.00 Flag question 题干 要使用变量score来存储学生某一门课程的成绩(百分制,可能出现小数部分),则最好将其定义为()类型的变量。选择一项: a.float b.Decimal c.int d.double 题目28 答案已保存 满分1.00 Flag question 题干 执行下列两条语句后,结果s2的值为()。String s=”abcdefgh”;String s2=s.substring(2,3);选择一项: a.“bc” b.”bcd” c.“cd” d.”cde” 题目29 答案已保存 满分1.00 Flag question 题干 C#是.NET应用程序唯一可用的语言 选择一项: 对 错 题目30 答案已保存 满分1.00 Flag question 题干 一个const变量必须在声明的同一条语句进行初始化,否则将会产生语法错误 选择一项: 对 错 题目31 答案已保存 满分1.00 Flag question 题干 单个数组元素传递给方法,且值在该方法中被修改,那么当调用方法完成执行时,该方法就包含了已经被修改的值。选择一项: 对 错 题目32 答案已保存 满分1.00 Flag question 题干 下面有关变量和常量的说法,正确的是()。选择一项: a.在程序运行过程中,变量的值是不能改变的,而常量是可以改变的 b.常量在内存中的存储单元是固定的,变量是变动的。c.常量定义必须使用关键词const d.在给常量赋值的表达式中不能出现变量 题目33 答案已保存 满分1.00 Flag question 题干 以下程序的输出结果是()。using system;class Example1 { public static void main(){ int a=5,b=4,c=6,d; Console.WriteLine(“{0}”,d=a>b?(a>c?a:c):b);} } 选择一项: a.5 b.4 c.6 d.0 题目34 答案已保存 满分1.00 Flag question 题干 表达式(x<=y && y>4)的值在x小于等于y或者y大于4的情况下为真 选择一项: 对 错 题目35 答案已保存 满分1.00 Flag question 题干 程序设计方法主要分为结构化程序设计方法和面向对象程序设计方法。选择一项: 对 错 题目36 答案已保存 满分1.00 Flag question 题干 下列语句中,不能够正确定义长度为4的数组a的语句是()。选择一项: a.int[ ] a=new int[4]{1,2,3,4};b.int[ ] a= {1,2,3,4};c.int[ ] a=new int[4]{1,2,3 };d.int[ ] a=new int[ ]{1,2,3,4};题目37 答案已保存 满分1.00 Flag question 题干 C#中每个int 类型的变量占用()个字节的内存。选择一项: a.8 b.2 c.1 d.4 题目38 答案已保存 满分1.00 Flag question 题干 面向对象程序设计方法完全摆脱了结构化程序设计方法,它是以类和对象为核心的一种全新的程序设计方法。选择一项: 对 错 题目39 答案已保存 满分1.00 Flag question 题干 NET Framework的引入是Visual Studio的一个标志性改进,.NET Framework的CLR充当了Visual Studio开发语言的“虚拟机”,是Visual Studio具有跨平台的特性的根本原因。选择一项: 对 错 题目40 答案已保存 满分1.00 Flag question 题干 已知a, b, c均为整型变量,表达式 b = a =(b = 20)+100 的值等于()。选择一项: a.100 b.20 c.true d.120 C#源程序文件的扩展名是()。选择一项: a..cs b..vb c..cpp d..c 题目2 C#中每个int 类型的变量占用()个字节的内存。选择一项: a.2 b.1 c.4 d.8 题目3 Visual C# 2008工具箱的作用是()。选择一项: a.显示指定对象的属性 b.显示和管理所有文件和项目设置,以及对应用程序所需的外部库的引用 c.编写程序代码 d.提供常用的数据控件、组件、Windows窗体控件等 题目4 现有如下程序 using system;class Example1 { public static voidMain(){ int x=1,a=0,b=0;switch(x){ case 0:b++;break;case 1:a++;break;case 2:a++;b++;break;} Console.WriteLine(“a={0},b={1}”,a,b);} } 当程序运行时,其输出结果是()。选择一项: a.a=1,b=0 b.a=2,b=1 c.a=2,b=2 d.a=1,b=1 题目5 解决方案资源管理器窗口的功能是()。选择一项: a.显示指定对象的属性 b.编写程序代码 c.提供常用的数据控件、组件、Windows窗体控件等 d.显示一个应用程序中所有的属性以及组成该应用程序的所有文件 题目6 为了将字符串str=“123,456”转换成整数123456,应该使用以下哪条语句?()选择一项: a.int Num = str.Parse(int); b.int Num = int.Parse(str,System.Globalization.NumberStyles.AllowThousands);c.int Num = int.Parse(str);d.int Num =(int)str; 题目7 下列数据类型中,不属于基本数据类型的是()。选择一项: a.数值类型 b.结构类型 c.布尔类型和对象类型 d.字符类型和字符串类型 题目8 下列语句中,不能够正确定义长度为4的数组a的语句是()。选择一项: a.int[ ] a= {1,2,3,4};b.int[ ] a=new int[4]{1,2,3 };c.int[ ] a=new int[4]{1,2,3,4};d.int[ ] a=new int[ ]{1,2,3,4};题目9 下面赋值正确的是()。选择一项: a.string str=’good’;b.char ch=“a”;c.double dNum=1.34;d.float fNum=1.5;题目10 下面关于命名空间的说法,错误的是()。选择一项: a.C#中,命名空间可有可无,看需要来定义和使用 b.使用命名空间的好处是,不但在不同命名空间中的成员可以重名,而且在同一个命名空间中的成员也可以重名 c.命名空间为程序的逻辑结构提供了一种良好的组织方法 d.同一个命名空间中的成员不能重名,不同命名空间中的成员可以重名 题目11 下面有关变量和常量的说法,正确的是()。选择一项: a.常量定义必须使用关键词const b.在程序运行过程中,变量的值是不能改变的,而常量是可以改变的 c.常量在内存中的存储单元是固定的,变量是变动的。d.在给常量赋值的表达式中不能出现变量 题目12 下面正确的字符常量是()。选择一项: a.“c” b.'“' c.'K' d.'” 题目13 项目文件的扩展名是()。选择一项: a.cs b.proj c.sln d.csproj 题目14 要使用变量score来存储学生某一门课程的成绩(百分制,可能出现小数部分),则最好将其定义为()类型的变量。选择一项: a.int b.Decimal c.double d.float 题目15 已定义下列变量:int n;float f;double df;df=10;n=2;下列语句正确的是()选择一项: a.f=df b.f=12.3 c.n=df d.df=n=100;题目16 已知a, b, c均为整型变量,表达式 b = a =(b = 20)+100 的值等于()。选择一项: a.100 b.20 c.true d.120 题目17 以下程序的输出结果是()。using system;class Example1 { public static void main(){ int a=5,b=4,c=6,d; Console.WriteLine(“{0}”,d=a>b?(a>c?a:c):b);} } 选择一项: a.5 b.4 c.6 d.0 题目18 以下装箱、拆箱语句中,错误的有()。选择一项: a.object obj=100;int m= obj;b.object obj=100;int m=(int)obj;c.object obj=(object)100;int m=(int)obj;d.object obj=(int)100;int m=(int)obj;题目19 执行程序段 int count=0;while(count<=7);Console.WriteLine(count);的输出结果是()。选择一项: a.3 b.2 c.4 d.死循环 题目20 执行下列两条语句后,结果s2的值为()。String s=”abcdefgh”; String s2=s.substring(2,3);选择一项: a.“bcd” b.”cd” c.“cde” d.”bc” 题目21 C#认为变量number和NuMbEr是等效的 选择一项: 对 错 题目22 C#是.NET应用程序唯一可用的语言 选择一项: 对 错 题目23 NET Framework的引入是Visual Studio的一个标志性改进,.NET Framework的CLR充当了Visual Studio开发语言的“虚拟机”,是Visual Studio具有跨平台的特性的根本原因。选择一项: 对 错 题目24 String类Trim方法可以删除字符串开始和结尾的所有空格 选择一项: 对 错 题目25 String类方法ToUpper只将字符串的首写字母大写 选择一项: 对 错 题目26 变量类型float可以被提升为double型 选择一项: 对 错 题目27 表达式(x<=y && y>4)的值在x小于等于y或者y大于4的情况下为真 选择一项: 对 错 题目28 程序设计方法主要分为结构化程序设计方法和面向对象程序设计方法。选择一项: 对 错 题目29 单个数组元素传递给方法,且值在该方法中被修改,那么当调用方法完成执行时,该方法就包含了已经被修改的值。选择一项: 对 错 题目30 公共语言运行库(CLR)要求程序员管理他们自己的内存 选择一项: 对 错 题目31 计算机可以直接执行机器语言、但汇编语言和高级程序设计语言需要编译成机器语言后才能被执行。选择一项: 对 错 题目32 面向对象程序设计方法虽然是一种主流的设计方法,但类中成员函数的设计仍然离不开结构化程序设计方法。选择一项: 对 错 题目33 面向对象程序设计方法完全摆脱了结构化程序设计方法,它是以类和对象为核心的一种全新的程序设计方法。选择一项: 对 错 题目34 所有的变量在声明它们的时候必须给出数据类型 选择一项: 对 错 题目35 无论使用那种.NET语言,MSIL是所有的.NET程序所编译成的通用中间格式 选择一项: 对 错 题目36 一个const变量必须在声明的同一条语句进行初始化,否则将会产生语法错误 选择一项: 对 错 题目37 一个数组同时可以存储很多不同类型的值 选择一项: 对 错 题目38 与Java一样,Visual Studio.NET也具有跨平台的特性,其原因在于它引入Java的 JVM。选择一项: 对 错 题目39 语句while(x>10 && x<100);在10 对 错 题目40 在程序执行时,注释使得//后面的文本打印在屏幕上 选择一项: 对 错 集合声明:类B可以换成任意object对象 1、CollectionBase 类A继承CollectionBase类,通过CollectionBase的成员List实现类A的Add(类 B)、Remove(类B)和RemoveAt(类B)方法: publicvoidAdd(类B newB) {List.Add(newB);} publicvoidRemove(类B newB) {List.Remove(newB);} publicvoidRemoveAt(int index) {List.RemoveAt(index);} 在类A中建立索引可以按类似数组的方法访问。 public 类B this[int index] {get{return(类B)List[index];} set{List[index]=value;} } 利用CollectionBase的成员InnerList(ArrayList对象)实现类A的Contains()方法: publicboolContains(类B newB) { returnInnerList.Contains(newB); } 注意:InnerList是ArrayList类实例,其Contains方法通过调用Object.Equals确定相等性,Equals默认实现仅支持引用相等。对于引用类型,相等定义为对象相等,即这些引用是否引用同一对象。对于值类型,相等定义为按位相等。 可以在类B中重写Object.Equals方法和GetHashCode()方法。publicoverrideboolEquals(objectobj) {//Check for null and compare run-time types.if(obj == null || GetType()!= obj.GetType())returnfalse; B b =(B)obj; return(比较逻辑); } publicoverrideintGetHashCode(){„„} 2、DictionaryBase 类A继承DictionaryBase类,通过DictionaryBase的成员 Dictionary(IDictionary类型的接口),实现类A的 Add(object key,类B)和Remove(object key,类B)方法: publicvoidAdd(object key,类B newB) {Dictionary.Add(key,newB);} publicvoidRemove(object key,类B newB) {Dictionary.Remove(key,newB);} 在类A中建立索引可以按类似数组的方法访问。 public 类B this[object index] {get{return(类B)Dictionary[index];} set{Dictionary[index]=value;} } 利用DictionaryBase的接口成员Dictionary实现类A的Contains()方法: publicboolContains(object key) { returnDictionary.Contains(key); } 3、迭代器 对于继承CollectionBase类的A,使用 foreach(BsourceBin类A对象){} 对于继承DictionaryBase类的A,使用 foreach(DictionaryEntrysourceBin类A对象){source.Value.} 对于类迭代,使用方法GetEnumerator(),返回类型是IEnumerator;类成员迭代使用IEnumerable(),返回类型是IEnumerable; 例如继承DictionaryBase类的A的迭代器,public new IEnumeratorGetEnumerator() {foreach(object b in Dictionary.Values) yield return(B)b; } 以后使用foreach循环时,可按照类似继承CollectionBase类的的方式使用。 4、浅度复制与深度复制 浅度复制:简单地按照成员复制对象可以通过派生于System.Object的MemberwiseClone()方法来完成,这是一个受保护的方法,但是很容易在对象上定义一个调用该方法的公共方法例如GetCopy()。这个方法的复制功能成为浅复制。浅拷贝是对引用类型拷贝地址,对值类型直接进行拷贝,但是string类例外,因为string是readonly的,当改变string类型的数据值时,将重新分配了内存地址。数组、类也是浅度复制,而结构体、数值型、枚举是深度复制。 深度复制:需要深度复制的类A添加ICloneable接口,实现该接口的Clone()方法。 public object Clone() {A newA=new A(); object []arr=new object[维度];//object 可以是数值类型,string //不能使用newA.arr=arr;因为通过数组名赋值引用同一地址,是浅度复制 arr.CopyTo(newA.arr,0); returnnewA;} 假设类A中有成员对象类B实例myB,则在类B定义中也要实现ICloneable的Clone()方法,class B:ICloneable { public object Clone(){„„} } 然后在类A的Clone方法中,newA.myB=myB.Clone(); 比较 1、is运算符 检查对象是否是给定类型或者是否可以转换为给定类型,是则返回true。 如果type是类类型,operand也是该类型,或继承该类型、封箱到该类型,为true 如果type是接口类型,operand也是该类型,或实现该接口的类型,为true 如果type是值类型,operand也是该类型,或拆箱到该类型,为true2、运算符重载 public static 返回类型 operator 需重载的运算符(参数„„){} 注意不能重载赋值运算符,&&和||运算符,但可重载&和|;有些运算符需成对重载,如“<”和“>” 3、IComparable接口 类A实现IComparable接口的方法intCompareTo(objectobj)后,利用成员为类A的实例的ArrayList或Array类可以调用Sort()方法,按CompareTo(objectobj)的方法排序。 4、IComparer接口 类A实现IComparer接口的方法intCompare(objectx, objecty)后,利用ArrayList或Array类可以调用Sort(IA)方法(IComparer IA=new A()),按 Compare(,)方法排序。注意ArrayList或Array类的实例不一定是类A。也可以在类A中定义一个公用动态接口成员IComparer ID,这样可以直接调用Sort(ID)。另外,在Compare方法中可以调用Comparer.Default.Compare(,)方法,实现特定的关键字排序。Default是Compare类的动态实例。 转换 1、隐式和显示转换 在没有继承关系,没有共享接口的类型之间转换时,必须定义类型之间的隐式和显示转换。public classA {„„ //定义A到B的隐式转换 public staticimplicit operatorzhuanB(Aa){„„ return } } public classB {„„ //定义B到A的显式转换 public staticexplicit operatorzhuanA(Bb){„„return } } 2、as运算符 把类型转换为给定类型。 operand类型是type类型,或可以隐式转换为type类型,或封箱到type类型 如果不能转换,则表达式的结果是null 异常处理 Exception:所有异常对象的基类。 SystemException:运行时产生的所有错误的基类。 IndexOutOfRangeException:当一个数组的下标超出范围时运行时引发。NullReferenceException:当一个空对象被引用时运行时引发。 InvalidOperationException:当对方法的调用对对象的当前状态无效时,由某些方法引发。 ArgumentException:所有参数异常的基类。 ArgumentNullException:在参数为空(不允许)的情况下,由方法引发。ArgumentOutOfRangeException:当参数不在一个给定范围之内时,由方法引发。 InteropException:目标在或发生在CLR外面环境中的异常的基类。ComException:包含COM类的HRESULT信息的异常。 SEHException:封装Win32结构异常处理信息的异常。 SqlException:封装了SQL操作异常。 常见具体的异常对象: ArgumentNullException一个空参数传递给方法,该方法不能接受该参数ArgumentOutOfRangeException参数值超出范围 ArithmeticException出现算术上溢或者下溢 ArrayTypeMismatchException试图在数组中存储错误类型的对象 BadImageFormatException图形的格式错误 DivideByZeroException除零异常 DllNotFoundException找不到引用的DLL FormatException参数格式错误 IndexOutOfRangeException数组索引超出范围 InvalidCastException使用无效的类 InvalidOperationException方法的调用时间错误 NotSupportedException调用的方法在类中没有实现 NullReferenceException试图使用一个未分配的引用OutOfMemoryException内存空间不够 StackOverflowException堆栈溢出 引用类型是类型安全的指针,它们的内存是分配在堆(保存指针地址)上的。String、数组、类、接口和委托都是引用类型。 强制类型转换与as类型转换的区别:当类型转换非法时,强制类型转换将抛出一System.InvalidCastException异常,而as不会抛出异常,它返回一个null值。用using创建别名:using console = System.Console;访问限定符: public 该成员可以被其他任何类访问 protected 该成员只能被其派生类访问 private 该成员只能被本类的其他成员访问 internal 该成员只能在当前编译单元的其他成员访问 带参数列表和返回值的Main方法: class Test { public static int Main(string[] args) { foreach(string arg in args) { ...} } } 构造函数(constructor)包括实例构造函数和静态构造函数。构造函数与类名相同,且不能有返回值。例: class TestClass { TestClass()//实例构造函数:可以访问静态成员和实例成员,用于初始化实例成员 { ...} static TestClass()//静态构造函数:只能访问静态成员,用于初始化静态成员 { ...} } 类的静态成员属于类所有,不必生成实例就可以访问,它是在载入包含类的应用程序时创建的,但静态方法不能访问类的实例变量和方法。通常,静态变量是在定义时就赋初始值的。类的实例成员属于类的实例所有,不创建实例对象就无法对其进行访问,实例成员可以访问类的 静态成员和其它实例成员。调用基类的析构函数: class A { public A() { ...} } class B { public B(): base()//调用基类的析构函数 { ...} } 常量:其值是在编译时设定的,必须是数值文字。默认状态下常量是静态的。例: class A { public const double pi = 3.1415;} 常量是编译时就确定的值,只读字段是在运行才能确定的值。比如运行时才能确定的屏幕分辨率。 只读字段只能在类的析构函数中赋值。静态只读字段: class A { public static readonly int ScreenWidth;//静态只读字段 static A() //静态析构函数 { ScreenWidth = 1024;//在静态析构函数中初始化 } } 在类的继承中,类的析构函数是不会被继承的。一个派生类只能从一个基类继承,不能同时从多个基类继承,但可以通过继承多个接口来达到相同目的。实现多继承的唯一方法就是使用接口。例: class MyFancyGrid: Control, ISerializable, IDataBound {...} 密封类是不能继承的类,抽象类不能被定义为密封类,且密封类的私有成员不能用protected修饰,只能用private。例: sealed class A {...} 关键字ref和out用于指定用引用方式传递方法的参数。 它们的区别是:ref参数必须初始化,而out参数不需要初始化。所以在方法处理代码依赖参数的初始化值时使用ref,不依赖初始化值时使用out。对out参数即使在传递前对其进行了初始化,其值也不会传递到方法处理函数内部。传递时系统会将其设为未初始化。所以在方法内部必须对out参数进行初始化。 方法重载时,必须参数数目和参数类型其中之一不同,返回值不同不能作为重载。C#不支持方法的默认值,只能通过方法重载来实现。例: class A { int Method(int a) { ...} void Method(int a, int b)//参数数目不同 { //返回值不同不能作为重载 ...} } params参数用于一个不定数目参数的方法,一般后面跟一个数组。例: class A { public void Method(params int[] i) { ...} } 方法的覆盖:指派生类覆盖基类的同名方法,有二种方法 1)第一种是在派生类要覆盖的方法前面加new修饰,而基类不需要作任何改动。这种方法的缺点是不能实现多态。例: class A { public void Method()//无需任何修饰 { ...} } class B: A //从基类继承 { new public void Method()//覆盖基类的同名方法 { ...} } class TestClass { A Instance = new B(); Instance.Method();//这时将调用类A的Method方法,而不是类B的Method方法 } 2)第二种是在派生类要覆盖的方法前面加override修饰,而基类的同名方法前面加virtual修饰。这样就能实现多态,例: class A { virtual public void Method() //基类定义虚方法 { //虚拟方法不能定义为private,因为private成员对派生类是无法访问的...} } class B: A //从基类继承 { override public void Method() //派生类覆盖基类的同名虚方法 { ...} } class TestClass { protected void Test() { A Instance = new B(); //定义一个实例,类型为基类,从派生类创建 //派生类总是能够向上转换为其基类 Instance.Method(); //将调用派生类B的Method方法,而不是基类的,这就是多态 } } 说明:new修饰的方法覆盖不能实现多态的原因,是因为使用new时编译器只会实现早期绑定(early binding)。即调用的方法在编译时就决定了:编译器看到Instance.Method()而Instance的类是A,就会调用类A的Method()方法。 override修饰的方法覆盖可以实现多态的原因,是因为实现了后期绑定(late binding)。使用override时强制编译器在运行时根据类的真正类型正确调用相应的方法,而不是在编译时。 而基类的同名方法必须加virtual修饰。 类的静态方法可能通过 类名.静态方法名 这种格式来调用,不能使用 实例名.静态方法名 这种方法调用。 因为类的静态方法为类所有(是属于类本身的),而非实例所有(不是属于类的实例的)。类的静态方法可以访问类的任何静态成员,但不能访问类的实例成员。C#中类的变量称为字段。类的public变量称为类的公共字段。 类的属性由一个protected(也可以是private)字段和getter和setter方法构成: class Address { protected string zipCode;//protected字段,注意大小写 public string ZipCode { get //getter方法 { return zipCode; } set //setter方法 { zipCode = value;//被传递的值自动被在这个value变量中 } };} 只读属性是指省略setter方法的属性,只读属性只能读取,不能设置。 属性也可以用限定符virtual,override和abstract修饰,功能同其他类的方法。 属性有一个用处称为懒惰的初始化(lazy initialization)。即在需要类成员时才对它们进行初始化。如果类中包含了很少被引用的成员,而这些成员的初始化又会花费大量的时候和系统资源的话,懒惰的初始化就很有用了。C#中数组对象共同的基类是System.Array。将数组声明为类的一个成员时,声明数组与实例化数组必须分开,这是因为只能在运行时创建了类的实例对象之后,才能实例化数组元素值。声明: int[] intArray;//一维数组 int[,] int3Array;//三维数组 初始化: intArray = new int[3] {1,2,3};int[,] int2Array = new int[2,3] {{1,2,3},{4,5,6}};//声明时可以初始化 遍历: 1)一维数组 for(int i = 0;i < intArray.Length;i++);//Array.Length返回数组所有元素的个数 foreach(int i in intArray);for(int i = 0;i < intArray.GetLength(0);i++);//Array.GetLength(0)返回数组第一维的个数 2)多维数组 for(int i = 0;i < int3Array.GetLength(0);i++)//遍历三维数组 for(int j = 0;j < int3Array.GetLength(1);j++) for(int k = 0;k < int3Array.GetLength(2);k++) { ...} 数组的维数就是该数组的秩(Rank)。Array.Rank可以返回数据的秩。锯齿数组(jagged Array)是元素为数组的数组,例: int[][] jaggedArray = new int[2][];//包含二个元素,每个元素是个数组 jaggedArray[0] = new int[2];//每个元素必须初始化 jaggedArray[1] = new int[3];for(int i = 0;i < jaggedArray.Length;i++)//遍历锯齿数组 for(int j = 0;j < jaggedArray[i].Length;j++) { ...} 类的属性称为智能字段,类的索引器称为智能数组。由于类本身作数组使用,所以用this作索引器的名称,索引器有索引参数值。例: using System;using System.Collections;class MyListBox { protected ArrayList data = new ArrayList(); public object this[int idx] //this作索引器名称,idx是索引参数 { get { if(idx >-1 && idx < data.Count) { return data[idx]; } else { return null; } } set { if(idx >-1 && idx < data.Count) { data[idx] = value; } else if(idx = data.Count) { data.Add(value); } else { //抛出一个异常 } } } } 接口是二段不同代码之间约定,通过约定实现彼此之间的相互访问。C#并不支持多继承,但通过接口可实现相同功能。当在接口中指定了实现这个接口的类时,我们就称这个类“实现了该接口”或“从接口继承”。一个接口基本上就是一个抽象类,这个抽象类中除了声明C#类的其他成员类型——例如属性、事件和索引器之外,只声明了纯虚拟方法。接口中可以包含方法、属性、索引器和事件——其中任何一种都不是在接口自身中来实现的。例: interface IExampleInterface { //property declaration int testProperty { get;} //event declaration event testEvevnt Changed; //mothed declaration function void testMothed(); //indexer declaration string this[int index] { get;set;} } 说明:定义接口时,在方法、属性、事件和索引器所有这些接口成员都不能用public之类的访问限定符,因为所有接口成员都是public类型的。因为接口定义了一个约定,任何实现一个接口的类都必须定义那个接口中每一个成员,否则将编译失败。例: using System;public class FancyControl { protected string data; public string Data { get {return this.data;} set {data = value;} } } interface IValidate { bool Validate();//接口方法 } public class MyControl: FancyControl, IValidate { public MyControl() { data = “my control data”; } public bool Validate()//实现接口 { if(data == “my control data”) return true; else return false; } } class InterfaceApp { MyControl myControl = new MyControl(); IValidate val =(IValidate)myControl;//可以将一个实现某接口的类,转换成该接口 bool success = val.Validate();//然后可调用该接口的方法 } 也可以用:bool success = myControl.Validate();这种方法来调用Validate方法,因为Validate在类MyControl中是被定义成public的,如果去除public,Validate方法被隐藏,就不能用这种方法调用了,这样隐藏接口方法称为名字隐藏(name hiding)。可以用:类实例 is 接口名 来判断某个类是否实现了某接口,例: myControl is IValidate //MyControl类的实例myControl是否实现了IValidate接口 当然,也可用as来作转换,根据转换结果是否为null来判断某个类是否实现了某接口,例: IValidate val = myControl as IValidate;if(null == val){...//没有实现IValidate接口 } else {...//实现了IValidate接口 } 如果一个类从多个接口继承,而这些接口中如果定义的同名的方法,则实现接口的方法时,必须加接口名来区别,写成 接口名.方法名。假设Test类从IDataStore和ISerializable二个接口继承,而这二个接口都有SaveData()方法,实现SaveData()方法时必须写成: class Test: ISerializable, IDataStore { void ISerializable.SaveData() { ...} void IDataStore.SaveData() { ...} } 如果一个类从多个接口继承,为了方便可以定义一个新的接口,这个接口继续多个接口,然后类直接从这个接口继承就可以了,这个叫合并接口。例: interface ISaveData: ISerializable, IDataStore { //不需要定义任何方法或成员,只是用作合并 } class Test: ISaveData //只要继承ISaveData就可以了 {...} C# 操作符优先级(从高到低) 初级操作符()x.y f(x)a[x] x++ x--new typeof sizeof checked unchecked 一元操作符 +位移操作符 << >> 关系操作符 < > <= >= is 等于操作符 == 逻辑与 & 逻辑异或 ^ 逻辑或 | 条件与 && 条件或 || 条件操作符 ?: 赋值操作符 = *= /= %= +=-= <<= >>= &= ^= |= 所有的二元操作符除赋值符外都是左联合的,即从左到右计算。 typeof()运算符可以从一个类名得到一个System.Type对象,而从System.Object对象继承来的GetType()方法则可从一个类实例来得到一个System.Type对象。例: Type t1 = typeof(Apple);//Apple是一个类名 Apple apple = new Apple();//apple是Apple类的一个实例 Type t2 = apple.GetType();//t1与t2是相同的 通过反射得到一个类的所有成员和方法: Type t = typeof(Apple);string className = t.ToString();//得到类名 MethodInfo[] methods = t.GetMethods();//得到所有方法 foreach(MethodInfo method in methods){ //用method.ToString()得到方法名 } MemberInfo[] members = t.GetMembers();//得到所有成员 foreach(MemberInfo member in members){ //用member.ToString()得到成员名 } sizeof()操作符用来计算值类型变量在内存中占用的字节数(Bytes),并且它只能在unsafe(非安全) 代码中使用。例: static unsafe public void ShowSizes(){ int i, j; j = sizeof(short); j = sizeof(i);} 尽可能使用复合赋值操作符,它比不用复合赋值操作符的效率高。for语句的语法为: for(initialization;Boolean-expression;step) embedded-statement 在initialization和step部份还可以使用逗号操作符,例: for(int i = '0', j = 1;i <= 'xFF';i++, j++)for(int i = 1, j = 1;i < 1000;i += j, j = i!~ ++--true false 二元:+32)/ 9)* 5; } } 代表的(delegate)目的与C++中的函数指针相同,代表不是在编译时被定义的,而是在运行时被定义的。 代表主要有二个用途:回调(Callback)和事件处理(event)回调通常用于异步处理和自定义处理。例: class DBManager { static DBConnection[] activeConnections; //声明回调函数 public void delegate EnumConnectionCallback(DBConnection connection); public static void EnumConnections(EnumConnectionCallback callback) { foreach(DBConnection connection in activeConnections) { callback(connection);//执行回调函数 } } } //调用 class DelegateApp { public static void ActiveConncetionCallback(DBConnection connection)//处理函数 { ...} public void main() { //创建指向具体处理函数的代表实例(新建一个代表,让它指向具体的处理函数) DBManager.EmnuConnectionCallback myCallback = new DBManager.EmnuConnectionCallback(ActiveConncetionCallback); DBManager.EnumConnections(myCallback); } } //使用静态代表,上面的调用改为 class DelegateApp { //创建一个指向处理函数的静态代表 public static DBManager.EmnuConnectionCallback myCallback = new DBManager.EmnuConnectionCallback(ActiveConncetionCallback); public static void ActiveConncetionCallback(DBConnection connection) {...} public void main() { DBManager.EnumConnections(myCallback); } } //在需要时才创建代表,上面的调用改为 class DelegateApp { //将创建代表放在属性的getter方法中 public static DBManager.EmnuConnectionCallback myCallback { get { retun new DBManager.EmnuConnectionCallback(ActiveConncetionCallback); } } public static void ActiveConncetionCallback(DBConnection connection) {...} public void main() { DelegateApp app = new DelegateApp();//创建应用程序 DBManager.EnumConnections(myCallback); } } 可以将多个代表整合成单个代表,例: class CompositeDelegateApp { public static void LogEvent(Part part) { ...} public static void EmailPurchasingMgr(Part part) { ...} public static void Main() { //定义二个代表 InventoryManager.OutOfStockExceptionMethod LogEventCallback = new InventoryManager.OutOfStockExceptionMethod(LogEvent); InventoryManager.OutOfStockExceptionMethod EmailPurchasingMgrCallback = new InventoryManager.OutOfStockExceptionMethod(EmailPurchasingMgr); //整合为一个代表,注意后加的代表先执行(这里是先执行LogEventCallback) InventoryManager.OutOfStockExceptionMethod onHandExceptionEventsCallback = EmailPurchasingMgrCallback + LogEventCallback; //调用代表 InventoryManager mgr = new InventoryManager(); mgr.ProcessInventory(onHandExceptionEventsCallback); //InventoryManager类的ProcessInventory方法的原型为: //public void ProcessInventory(OutOfStockExceptionMethod exception); } } 可以根据需要将多个代表自由地组合成单个代表,例: class CompositeDelegateApp { //代表指向的处理函数(三个代表三个函数) public static void LogEvent(Part part) { ...} public static void EmailPurchasingMgr(Part part){...} public static void EmailStoreMgr(Part part) { ...} public static void Main() { //通过数组定义三个代表 InventoryManager.OutOfStockExceptionMethod[] exceptionMethods = new InventoryManager.OutOfStockExceptionMethod[3]; exceptionMethods[0] = new InventoryManager.OutOfStockExceptionMethod(LogEvent); exceptionMethods[1] = new InventoryManager.OutOfStockExceptionMethod(EmailPurchasingMgr); exceptionMethods[2] = new InventoryManager.OutOfStockExceptionMethod(EmailStoreMgr); int location = 1; //再定义一个代表(用于组合成单代表) InventoryManager.OutOfStockExceptionMethod compositeDelegate; //根据需要组合 if(location = 2) { compositeDelegate = exceptionMethods[0] + exceptionMethods[1]; } else { compositeDelegate = exceptionMethods[0] + exceptionMethods[2]; } //调用代表 InventoryManager mgr = new InventoryManager(); mgr.ProcessInventory(compositeDelegate); } } C#的事件遵循“发布——预订”的设计模式。在这种模式中,一个类公布能够出现的所有事件,然后任何的类都可以预订这些事件。一旦事件产生,运行环境就负责通知每个订户事件已经发生了。 当代表作为事件的处理结果时(或者说定义具有代表的事件),定义的代表必须指向二个参数的方法:一个参数是引发事件的对象(发布者),另一个是事件信息对象(这个对象必须从EventArgs类中派生)。例: using System; class InventoryChangeEventArgs: EventArgs //事件信息对象,从EventArgs类派生 {...//假设定义二个public属性string Sku和int Change } class InventoryManager //事件的发布者 { //声明代表 public delegate void InventoryChangeEventHander(object source, InventoryChangeEventArgs e); //发布事件,event关键字可将一个代表指向多个处理函数 public event InventoryChangeEventHandler onInventoryChangeHander; public void UpdateInventory(string sku, int change) { if(change == 0) return; InventoryChangeEventArgs e = new InventoryChangeEventArgs(sku, change); //触发事件 if(onInventoryChangeHandler!= null)//如果有预订者就触发 onInventoryChangeHandler(this, e);//执行代表指向的处理函数 } } class InventoryWatcher //事件的预订者 { public InventoryWatcher(InventoryManager mgr)//mgr参数用于联结发布者 { this.inventoryManager = mgr; //预订事件,用 += 调用多个处理函数 mgr.onInventroyChangeHandler += new InventoryManager.InventoryChangeEventHandler(onInventoryChange); //事件处理函数 void onInventroyChange(object source, InventroyChangeEventArgs e) { ...} InventoryManager inventoryManager; } } class EventsApp //主程序 { public static void Main() { InventoryManager inventoryManager = new InventoryManager(); InventoryWatcher inventoryWatcher = new InventoryWatcher(inventoryManager); inventoryManager.UpdateInventory(“111 006 116”,-2); inventoryManager.UpdateInventory(“111 006 116”, 5); } } Microsoft Windows NT和IBM OS/2等操作系统都支持占先型多任务。在占先型多任务执行中,处理器负责 给每个线程分配一定量的运行时间——一个时间片(timeslice)。处理器接着在不同的线程之间进行切换,执行相应的处理。在单处理器的计算机上,并不能真正实现多个线程的同时运行,除非运行在多个处理器 的计算机上。操作系统调度的多线程只是根据分配给每个线程时间片进行切换执行,感觉上就像同时执行。 上下文切换(context switching)是线程运行的一部分,处理器使用一个硬件时间来判断一个指定线程的时间片何时结束。当这个硬件计时器给出中断信号时,处理器把当前运行的线程所用的所有寄存器(registers)数据存储到堆栈中。然后,处理器把堆栈里那些相同的寄存器信息存放到一种被称为“上下文结构”的数据结构中。当处理器要切换回原来执行的线程时,它反向执行这个过程,利用与该线程相关的上下文结构,在寄存器里重新恢复与这一线程相关的信息。这样的一个完整过程称为“上下文切换”。多线程允许应用程序把任务分割为多个线程,它们彼此之间可以独立地工作,最大限度地利用了处理器时间。using System;using System.Threading;class SimpleThreadApp { public static void WorkerThreadMethod()//线程的执行体 { ...//执行一些操作 } public static void Main() { //创建一个线程代表指向线程的执行体,ThreadStart是创建新线程必须用到的代表 ThreadStart worker = new ThreadStart(WorkerThreadMethod); Thread t = new Thread(worker);//用线程代表创建线程 t.Start(); //执行线程 } } 可以通过两种方式来得到一个Thread对象:一种是通过创建一个新线程来得到,如上例;另一种在正在执行的线程调用静态的Thread.CurrentThread方法。 静态方法Thread.Sleep(int ms)可以让当前线程(它自动调用Thread.CurrentThread)暂停指定毫秒的时间。 如果使用Thread.Sleep(0)那么当前线程将一直处于等待中,直到另一个线程调用这个线程的实例方法Thread.Interrupt方法,等待才会结束。使用Thread.Suspend方法也能挂起线程,Thread.Suspend方法可以被当前线程或其他线程调用,而Thread.Sleep(0)只能由当前线程在执行体中调用。当线程用Thread.Suspend挂起时,必须用Thread.Resume方法恢复。不论Thread.Suspend方法调用了多少次,只要调用Thread.Resume方法一次就可以线程恢复执行。用Thread.Suspend方法并不会阻塞线程,调用立即返回。而Thread.Sleep(0)则会阻塞线程。所以确切地说Thread.Sleep(0)暂停线程,而不是挂起线程。 使用Thread.Abort方法可以终止正在执行的线程。当Thread.Abort方法被调用时,线程不会立即终止执行。运行环境将会等待,直到线程到达文档中所描述的“安全点”。如果要确保线程已经完全停止,可以使用Thread.Join方法。这是一个同步调用,同步调用意味着直到线程完全停止,调用才会返回。 Thread.Priority属性用于设置的线程的优先级。其值是Thread.ThreadPriority枚举值,可以设为Highest, AboveNormal,Normal, BelowNormal, Lowest。缺省值是Thread.ThreadPriority.Normal。 线程的同步是为了解决多个线程同时使用同一对象产生的一些问题。通过同步,可以指定代码的临界区(critical section),一次只有一个线程可以进入临界区。使用System.Monitor类(锁定与信号量)进行线程同步: using System;using System.Threading;public void SaveData(string text)//线程执行函数或线程执行函数调用的对象的方法 { ...//执行其他一些不需要同步的处理 Monitor.Enter(this);//获取对象的Monitor锁 ...//执行需要同步的处理 Monitor.Exit(this);//释放对象的Monitor锁 ...//执行其他一些不需要同步的处理 } 说明:当执行Monitor.Enter方法时。这个方法会试图获取对象上的Monitor锁,如果另一个线程已经拥有了这个锁,这个方法将会阻塞(block),直到这个锁被释放。 也可用C#的lock语句来获得和释放一个Monitor锁。上面同步写成:public void SaveData(string text)//线程执行函数或线程执行函数调用的对象的方法 { ...//执行其他一些不需要同步的处理 lock(this)//获取对象的Monitor锁,代码块执行完成后释放Monitor锁 { ...//执行需要同步的处理 } ...//执行其他一些不需要同步的处理 } 也可以使用System.Threading名称空间的Mutex类(互斥类)进行线程同步。与Monitor锁一样,一次只有一个线程能获得一个给定的互斥。但Mutex要慢得多,但它增加了灵活性。例: using System;using System.Threading;class Database { Mutex mutex = new Mutex(false);//创建一个互斥,但不立即获得它 //注意:创建互斥在需要同步的方法之外,实际上它只要创建一个实例 public void SaveData(string text)//需要同步的方法 { mutex.WaitOne();//等待获得互斥 ...//需要同步的处理 mntex.Close();//释放互斥 } } Mutex类重载了三个构造函数: Mutex() //创建并使创建类立即获得互斥 Mutex(bool initiallyOwned) //创建时可指定是否要立即获得互斥 Mutex(bool initiallyOwned, string muterName)//还可以指定互斥的名称 Mutex.WaitOne方法也重载了三次: Mutex.WaitOne() //一直等待 Mutex.WaitOne(TimeSpan time, bool exitContext)//等待TimeSpan指定的时间 Mutex.WaitOne(int milliseconds, bool exitContext)//等待指定的毫秒 线程的用法: 1)并发操作:比如一个程序监视多个COM口,当每个COM接到信息时执行一段处理时。2)复杂长时间操作:一个长时间的复杂操作可能会使界面停滞,停止用户响应,如果还允许用户停止它,或者显示进度条、显示操作执行进程信息时。 反射(Reflection)就是能够在运行时查找类型信息,这是因为.NET编译的可执行(PE)文件中包括MSIL和元数据(metadata)。 反射的中心是类System.Type。System.Type是一个抽象类,代表公用类型系统(Common Type System, CTS)中的一种类型。 using System;using System.Reflection;//反射命名空间,必须引用 public static void Main(string[] args){ int i = 6; Type t = i.GetType(); //根据实例得到类型 t = Type.GetType(“System.Int32”);//根据类型的字符名称得到类型 } 通过Assembly类可以得到已经编译.NET Framework程序的中所有类型,例: using System;using System.Diagnostics;//为了使用Process类 using System.Reflection;//为了使用Assembly类 class GetTypesApp { protected static string GetAssemblyName(string[] args) { string assemblyName; if(0 == args.Length)//如果参数为空,取当前进程的名称 { Process p = Process.GetCurrentProcess(); assemblyName = p.ProcessName + “.exe”; } else assemblyName = args[0];//取第一个参数,即当前运行程序名 return assemblyName; } public static void Main(string[] args) { string assemblyName = GetAssemblyName(args); Assembly a = Assembly.LoadFrom(assemblyName);//调用编译程序集 Type[] types = a.GetTypes(); //得到多个类型 foreach(Type t in types) //遍历类型数组 { ...//取得t.FullName,t.BaseType.FullName等类型信息 } } } 一个应用程序可以包括多个代码模块。若要将一个cs文件编译一个模块,只要执行下面的命令: csc /target:module 要编译的模块.cs //csc是C Sharp Compiler(C#编译器)然后在应用程序中using编译的模块.cs中的NameSpace即可应用了。要反射应用程序中所有代码模块(Module),只要: Assembly a = Assembly.LoadFrom(assemblyName);//应用程序的物理文件名 Module[] modules = a.GetModules();foreach(Module m in modules){...//显示m.Name等 } 后期绑定(latebinding),例: string[] fileNames = Directory.GetFiles(Environment.CurrentDirectory, “*.dll”);foreach(string fileName in fileNames){ Assembly a = Assembly.LoadFrom(fileName); Type[] types = a.GetTypes(); foreach(Type t in types) { if(t.IsSubclassOf(typeof(CommProtocol)))//判断是否有CommProtocol的派生类 { object o = Activator.CreateInstance(t);//生成实例 MethodInfo mi = t.GetMethod(“DisplayName”); mi.Invoke(o, null); //调用方法 } } } //带参数的例子 namespace Programming_CSharp { using System; using System.Reflection; public class Tester { public static void Main() { Type t = Type.GetType(“System.Math”); Object o = Activator.CreateInstance(t); // 定义参数类型 Type[] paramTypes = new Type[1]; paramTypes[0]= Type.GetType(“System.Double”); MethodInfo CosineInfo = t.GetMethod(“Cos”, paramTypes); //设置参数数据 Object[] parameters = new Object[1]; parameters[0] = 45; //执行方法 Object returnVal = CosineInfo.Invoke(o, parameters); Console.WriteLine(“The cosine of a 45 degree angle {0}”, returnVal); } } } 动态生成代码和动态调用的完整例子: //动态生成代码的部分 using System;using System.Reflection;using System.Reflection.Emit;//动态生成代码必须引用 namespace ILGenServer { public class CodeGenerator { public CodeGenerator() { currentDomain = AppDomain.CurrentDomain;//得到当前域 assemblyName = new AssemblyName();//从域创建一个程序集 assemblyName.Name = “TempAssembly”; //得到一个动态编译生成器,AssemblyBuilerAccess.Run表示只在内存中运行,不能保存 assemblyBuilder = currentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilerAccess.Run); //从编译生成器得到一个模块生成器 moduleBuilder = assemblyBuilder.DefineDynamicModule(“TempModule”); //模块生成器得到类生成器 typeBuilder = moduleBuilder.DefineType(“TempClass”, TypeAttributes.Public); //为类添加一个方法 methodBuilder = typeBuilder.DefineMethod(“HelloWord”, MethodAttributes.Public, null, null); //为方法写入代码,生成代码必须使用到IL生成器 msil = methodBuilder.GetILGenerator(); msil.EmitWriteLine(“Hello World”);msil.Emit(OpCodes.Ret);//最后还需要编译(build)一下类 t = typeBuilder.CreateType(); } AppDomain currentDomain; AssemblyName assemblyName; AssemblyBuilder assemblyBuilder; ModuleBuilder moduleBuilder; TypeBuilder typeBuilder; MethodBuilder methodBuilder; ILGenerator msil; object o; Type t; public Type T { get { return this.t; } } } } //动态调用的部分 using System;using System.Reflection;using ILGenServer;//引用动态生成代码的类 public class ILGenClientApp { public static void Main({ CodeGenerator gen = new CodeGenerator();//创建动态生成类 Type t = gen.T; if(null!= t) { object o = Activator.CreateInstance(t); MethodInfo helloWorld = t.GetMethod(“HelloWorld”);//为调用方法创建一个MethodInfo if(null!= helloWorld) { helloWorld.Invoke(o, null);//调用方法 } } } } 调用DLL using System;using System.Runtime.InteropServices;//为了使用DLLImport特性 class PInvokeApp { [DllImport(“user32.dll”, CharSet=CharSet.Ansi)] //CharSet.Ansi指定Ansi版本的函数(MessageBoxA),CharSet.Unicode指定Unicode版本的函数(MessageBoxW) static extern int MessageBox(int hWnd, string msg, string caption, int type);//声明DLL中的函数 //[DllImport(“user32.dll”, EntryPoint=“MessageBoxA”)] //用这种方法使用不同的函数名 //static extern int MsgBox(int hWnd, string msg, string caption, int type); //[DllImport(“user32.dll”, CharSet=CharSet.Unicode)] //调用Unicode版的DLL函数 //static extern int MessageBox(int hWnd, [MarshalAs(UnmanagedType.LPWStr)]string msg,// [MarshalAs(UnmanagedType.LPWStr)]string caption, int type);//将LPWStr翻译为string型,缺省情况系统只将LPStr翻译成string public static void Main() { MessageBox(0, “Hello, World!”, “CaptionString”, 0);//调用DLL中的函数 } } 例2,使用回调: class CallbackApp { [DllImport(“user32.dll”)] static extern int GetWindowText(int hWnd, StringBuilder text, int count); delegate bool CallbackDef(int hWnd, int lParam); [DllImport(“user32.dll”)] static extern int EnumWindows(CallbackDef callback, int lParam); static bool PrintWindow(int hWnd, int lParam) { StringBuilder text = new StringBuilder(255); GetWindowText(hWnd, text, 255); Console.WriteLine(“Window Caption: {0}”, text); return true; } static void Main() { CallbackDef callback = new CallbackDef(PrintWindow); EnumWindows(callback, 0); } } 关键字unsafe指定标记块在非控环境中运行。该关键字可以用于所有的方法,包括构造函数和属性,甚至还有方法中的代码块。关键字fixed负责受控对象的固定(pinning)。Pinning是一种动作,向垃圾收集(Garbage Collector, GC)指定一些不能被移动的对象。为了不在内存中产生碎片,.NET运行环境把对象四处移动,以便于最有效地利用内存。使用fixed后指定对象将不会被移动,所以就可以用指针来访问它。 C#中只能得到值类型、数组和字符串的指针。在数组的情况下,第一个元素必须是值类型,因为C#实际上是返回一个指向数组第一个元素的指针,而不是返回数组自身。& 取一个变量的内存地址(即指向该变量的指针)* 取指针所指变量的值-> 取成员 例:using System;class UnsafeApp { public static unsafe void GetValues(int* x, int* y) { *x = 6; *y = 42; } public static unsafe void Main() { int a = 1; int b = 2; GetValues(&a, &b); } } fixed语法为:fixed(type* ptr = expression)statements其中type也可以为非控类型,也可是void;expression是任何产生一个type指针的表达式;statements是应用的代码块。例: fixed(int* f = &foo.x)//foo是Foo类的一个实例,x是Foo类的一个int属性 { SetFooValue(f);//SetFooValue方法的定义为unsafe static void SetFooValue(int* x)} 传统的COM组件可以通过互操作层(COM Interop)与.NET运行环境交互。互操作层处理在托管运行环境和非托管区域中的COM组件操作之间传递所有的消息。 要使COM组件能在.NET环境中使用,必须为COM组件生成元数据。.NET运行环境用元数据层业判断类型信息。在运行时刻使用类型信息,以便生成RCW(Runtime Callable Wrapper,运行时可调用包装)。当.NET应用程序与COM对象交互时,RCW处理对COM对象的装载和调用。RCW还完成许多其他的工作,如管理对象标识、对象生存周期以及接口缓冲区。对象生存周期管理十分关键,因为.NET GC把对象到处移动,并且当对象不再使用时,自动处理这些对象。RCW服务告诉.NET,应用程序正与托管.NET组件交互,同时又使非托管COM组件“觉得”COM对象是被传统的COM客户端调用的。 为了为COM组件生成元数据包装,必须使用tlbimp.exe(TypeLib Importer)工具: tlbimp some_COM.tlb /out:som_COM.dll 1、.NET平台包括.NET框架和.NET开发工具等组成部分。.NET框架是整个开发平台的基础,包括公共语言运行库和.NET类库。.NET开发工具包括Visual Studio.NET集成开发环境和.NET编程语言。.NET框架(.NET Framework)是.NET开发平台的基础。.NET框架提供了一个跨语言的、统一的、面向对象的开发和运行环境。 2、在Visual Studio.NET集成开发环境下,可以开发多种不同类型的应用程序。最常见的有以下几种。 。控制台应用程序 。Windows应用程序 。ASP.NET网站 3、开发和运行控制台应用程序 创建一个控制台应用程序,主要包含以下步骤: (1)执行文件—》新建—》项目 (2)打开“新建项目”对话框,在“项目类型”列表中选择Visual c#节点下的Windows,在“模板”窗格中选择“控制台应用程序”项目模板,输入项目的名称、位置及 解决方案名称后,单击“确定”按钮。 (3)在打开的.cs文件中编写代码。 (4)运行程序。执行“调试”—》启动调试菜单命令,编译并运行程序 4、c#程序的基本结构 。using关键字的功能是用于导入其它命名空间中定义的类型,包括.NET类库。例如,代码中使用的console.readline方法实际上是一个简写,其全称是system.console.readline,但由于在代码的开始使用using指令引入了system命名空间,所以后面可以直接使用console.readline来进行输入。 。namespace 即“命名空间”,也称“名称空间”。命名空间是Visual Studio.NET中的各种语言使用的一种代码组织的形式,当编译一个解决方案时,系统会用项目名称做名字,生成一个namespace,并把类都放在这个namespace里面。第二篇:应用软件开发C#第一次作业
第三篇:C#学习心得
第四篇:C#总结
第五篇:c#读书笔记