C#进阶教程.doc_第1页
C#进阶教程.doc_第2页
C#进阶教程.doc_第3页
C#进阶教程.doc_第4页
C#进阶教程.doc_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

十二C#进阶一这次我要向大家讲的是C#中的属性.属性是什么呢,比如说我是男的,男就是我的一人属性.我是一个大一的学生,大一也是我的一个属性.属性就是一个对象的性质.很简单吧,呵呵!下面,我给出两个例子,第一个例子出明了如何声明一个可以修改的属性,另一个例了建立了一个抽象的属性(Abstract),并且说明了如何在子类中丢弃它.好,下面让我们开始吧. 例子一: class Person private string myName = N/A; private int myAge = 0; / 声明一个字符型的属性Name public string Name get return myName; set myName = value; / 声明一个int型的Age属性 public int Age get return myAge; set myAge = value; public override string ToString() return Name = + Name + , Age = + Age; static void Main(string args) Console.WriteLine(Simple Properties); / 建立一个Person的实例 Person person = new Person(); / file:/打印出它的属性 Console.WriteLine(Person details - 0, person); / 对属性进行一些设置 person.Name = Joe; person.Age = 99; Console.WriteLine(Person details - 0, person); / 增加年龄 person.Age += 1; Console.WriteLine(Person details - 0, person); Console.ReadLine(); 这个例子的输出是: Simple Properties Person details - Name = N/A, Age = 0 Person details - Name = Joe, Age = 99 Person details - Name = Joe, Age = 100 从上面的程序我们可以看出,一个类的属性的设置,借用了VB的概念,和JAVA中不尽相同了.(这就是M$,TMD!)有的朋友可能很奇怪,为什么我们可以用Console.WriteLine()来打印一个对象person呢.其实道理很简单,和在JAVA中的一样,当调节器用一个打印方法时,这个对象自动调用它的ToString()(在JAVA中是toString,TMD,又差点犯错!)方法. override这个关键字大概就是覆盖父类的方法吧,这是不是有点多余?我们可以看到,一个对象的属性的设置是通过一个get()和set()组合来完成的,当然,还有一个value这个东东.补充一下,你还可以控制一个属性的读/写权限,只是把get()和set()简单地去掉就可以了,比如你不要写的属性,就不要set()就可以了,如果你不要读,就不要get()吧.总得感觉,C#在这点上没有JAVA来的灵活(完了,又要被盖痴打了!). 第二个例子: 这个例子说明了如何建立抽象的属性(Abstract),什么是抽象的属性呢,所谓的抽象的属性呢,就是一个抽象类并不提供执行属性存取程序,并且,他可以在子类中被忽略.下面的例子有三个文件,你要分别编译它们才能得到结果,它们是: abstractshape.cs: Shape类,包含一个Area抽象属性 shapes.cs: Shape的子类 shapetest.cs: 显示程序. 要编译这些程序,运行:csc abstractshape.cs shapes.cs shapetest.cs就可以了.运行完之后,它会产生shapetest.exe这个可执行程序. public abstract class Shape private string myId; public Shape(string s) Id = s; / 这句调用了Id属性的set构建器 public string Id get return myId; set myId = value; public abstract double Area get; public override string ToString() return Id + Area = + Area.ToString(F); /return Id + Area = + Area.ToString(f2); 看这个程序, 实际上非常地简单,当这个类对的对象被建立时,初始化部分为007-010,它把建立对象的参数s给了Id这个属性.然后进行了上一个例子的操作.实际上,我们可以把抽象属性与JAVA中的接口(Interface)相比,它们只提拱一个方法的名称,而不提供这个方法的内容.就像Area这个抽象属性,有一个get,但是它并没有指定get方法(也许它不能称之为方法)里的内容,即要get做什么事情. 这个事情,由它的子类来做. 第二个文件:在这个文件中,一个类覆盖了(override)了Area属性. public class Square : Shape private int mySide; public Square(int side, string id) : base(id) mySide = side; public override double Area get return mySide * mySide; public class Circle : Shape private int myRadius; public Circle(int radius, string id) : base(id) myRadius = radius; public override double Area get return myRadius * myRadius * System.Math.PI; public class Rectangle : Shape private int myWidth; private int myHeight; public Rectangle(int width, int height, string id) : base(id) myWidth = width; myHeight = height; public override double Area get return myWidth * myHeight; 这个例子就有些让我们一头雾水了,:是干什么的,好象是继承,相当于JAVA中的extends吧.我想是的.我们先看一看吧. 下面的第三个文件就是一个测试文件了,很简单,大家看一看. public class TestClass public static void Main() Shape shapes = new Square(5, Square #1), new Circle(3, Circle #1), new Rectangle( 4, 5, Rectangle #1) System.Console.WriteLine(Shapes Collection); foreach(Shape s in shapes) System.Console.WriteLine(s); 从这个例子上看,:这个符号的确是extends的意思,就是继承.继承是什么意思,说白了,就是生孩子的意思.比如下面一句sunwenson extends sunwen,这名就是说sunwenson这个类继承了sunwen,sunwenson这个类有sunwen类的所有东西,同时可以添加和删除sunwen中的一些东西.就这么简单,但是这是现代软件发展的一项重要技术,因为它可以使软件的重用性大大提高.唉,这些就只有大三大四的人说了,我就没资格了.呵呵. 这个程序的输出是: Shapes Collection Square #1 Area = 25.00 Circle #1 Area = 28.27 Rectangle #1 Area = 20.00 C#进阶教程二言归正传,我现在要说的是库(libraries),和大家一起学习如何用C#建立一个DLL文件.说起DLL,肯定是无人不知,无人不晓,这个WINDOWS的典型代表,同时也经常是大家功击的对象.呵呵,不管怎么样,学还是要学的.我们下面就开始,如何用命令行方式将一个C#程序编译成DLL,和如何在客户端使用他. 这个例子包括两个文件,一个是Factorial.cs,作用是计算一个数字的阶乘.还有一个是DigitCounter.cs,作用是计算传过来的字符串参数中的数字的数目. 我们可以这样来建立库,在命令行方式下这样做: csc /target:library /out:Functions.dll Factorial.cs DigitCounter.cs 下面讲一下各个参数的用法: /target:library:向系统指出输出的是一个DLL库,而不是一个EXE的可执行文件. /out:Functions.dll:指定输出的DLL的文件名,即Functions.dll,一般地,如果你省略了第一个参数,那么默认的文件名将是第一个文件的文件名,即Factorial.dll. 下面我们再来建立一个文件,即使用这个库的文件,叫客户端文件,FunctionClient.cs.建立好后,用下面的语名编译: csc /out:FunctionTest.exe /R:Functions.DLL FunctionClient.cs 下面说一下这个编译语句的用法: /out:FunctionTest.exe:指出输出的文件名是FunctionTest.exe /R:Functions.DLL:指出要引用的库,如果不是在当前目录下,必须要指出其的完整路径. 下面我就把这几个文件的代码写在下面:namespace Functions public class Factorial public static int Calc(int i) return(i = 1) ? 1 : (i * Calc(i-1); 这是Factorial.cs这个文件的代码.在003行中,namespace的意思是名字空间,据M$的介绍,库必须根据它的名字空间打包,以使.NET能够正确地载入你的类. 下面是DigitCounter.cs这个文件的内容: public class DigitCount public static int NumberOfDigits(string theString) int count = 0; for (int i = 0; i theString.Length; i+) if (Char.IsDigit(theString,i) count+; return count; 注意,这个例子中的namespace应与第一个的一致,因为它们是同一个库中的.NumberOfDigits方法计算了参数中的数字的个数. 第三个文件是FunctionClient.cs 我们知道,一个库一旦建立,就可以被别的类利用(废话,要不然怎么叫库呢?).下面的C#程序就利用了我们刚才建立的库中的类. using System;using Functions; public static void Main(string args) Console.WriteLine(Function Client); if (args.Length = 0) Console.WriteLine(Usage: FunctionTest . ); return; for (int i = 0; i args.Length; i+) int num = Int32.Parse(args); Console.WriteLine(The Digit Count for String is , args, DigitCount.NumberOfDigits(args); Console.WriteLine(The Factorial for is , num, Factorial.Calc(num); “using Functions“,指明了引用Functions.DLL这个类. 如果我们在命令行中键入如下命令,就可以看到输出: FunctionTest 3 5 10 输出: Function Client The Digit Count for String is The Factorial for is The Digit Count for String is The Factorial for is The Digit Count for String is The Factorial for is注意:当你运行这个.EXE文件时,它引用的DLL文件可以是在当前目录,子目录,或是CORPATH这个环境变量.CORPATH这个环境变量是在.NET环境中的类路径,用来指引系统寻找类.说白了,就是JAVA中的CLASSPATH,明白了吧,呵呵.C#进阶教程三在C#中,如果你在声明一个方法的时候用了virtual这个关键字,那么,在派生类中,你就可以使用override或者new关键字来弃用它或是忽略它.如果你在父类中用了virtual这个关键字,而在其派生类中又没有用override或new关键字,而直接引用一个同名方法的话,编译器将会报错,并将以new方式,即忽略派生类中的方法的方式来运行.下面的例子可以帮助你来理解: / Versioningversioning.cs public class MyBase public virtual string Meth1() return MyBase-Meth1; public virtual string Meth2() return MyBase-Meth2; public virtual string Meth3() return MyBase-Meth3; class MyDerived : MyBase public override string Meth1() return MyDerived-Meth1; public new string Meth2() return MyDerived-Meth2; public string Meth3() / 系统在这里将会有一个警告,并且将会隐藏方法Meth3() return MyDerived-Meth3; public static void Main() MyDerived mD = new MyDerived(); /* MyBase mB = (MyBase)mD; System.Console.WriteLine(mB.Meth1(); System.Console.WriteLine(mB.Meth2(); System.Console.WriteLine(mB.Meth3(); /* /+ /System.Console.WriteLine(mD.Meth1(); /System.Console.WriteLine(mD.Meth2(); /System.Console.WriteLine(mD.Meth3();/+ Console.ReadLine(); 输出:MyDerived-Meth1 MyBase-Meth2 MyBase-Meth3可以很明显地看出来,后两个new关键字的输出是父类中的方法的输出,所以可以看出,new这个关键字的作用是如果在以前的版本中有这个方法,就沿用以前的方法,而不用我现在方法内容.而virtual的方法的作用正好相反,它的作用是如果在父类中有这样一个方法,则用我现在写的方法内容,让以前的滚蛋!不过,这里用new好象不太好,让人误解(糟了,盖痴又要打我了!&*%$#). 如果你把星号注释之间的代码去掉,改为加号注释的代码,输出又变为:MyDerived-Meth1MyDerived-Meth2MyDerived-Meth3这又说明了什么呢,说明了派生类的对象只有在被父类重塑的时候,override和new关键字才会生效.呵呵,这样说的确有点难以理解,大家只有自己动手,才能搞清楚这其中的机关,所谓实践是检验C#的唯一标准,哈哈! 在C#中,你可以自由地为在派生类中为加入一个方法,或者覆盖父类的方法,如下所示,非常地简单:C#进阶教程四好了,言归正传.我要说的是C#中的结构(struct),注意,我在这里说的结构不是指的C#的语言结构.这里所说的是一种与类(class)相对的东西,下面我就与类相对比,来说一说这个struct. 下面的这个例子讲述了如何建立一个具有属性,方法和一个字段的结构.并讲述如何使用他. struct SimpleStruct private int xval; public int X get return xval; set if (value 100) xval = value; public void DisplayX() Console.WriteLine(The stored value is: 0, xval); class TestClass public static void Main() SimpleStruct ss = new SimpleStruct(); ss.X = 5; ss.DisplayX(); Console.ReadLine(); 输出是: The stored value is: 5 从上面的例子中我们可以看到结构和类似乎是一样的.的确,如果你用类去重亲写这个程序,结果是一样的.但是,很明显,两个一样的东西是不可能一起出现的. 结构(struct)是值(value)型的,而类是参考型的.这样,你就可以用结构建立像内建类型那样的对象了. 还有就是如果你用一个new关键字建立一个类的实例的时候,它是以堆(heap)来分配的,而用new来建立一个结构的的实例的时候,它是以栈(stack)来分配.这会给我们提高很多性能(M$说的).好了,让我们再来看下面的例子吧: class TheClass public int x; struct TheStruct public int x; class TestClass public static void structtaker(TheStruct s) s.x = 5; public static void classtaker(TheClass c) c.x = 5; public static void Main() TheStruct a = new TheStruct(); TheClass b = new TheClass(); a.x = 1; b.x = 1; structtaker(a); classtaker(b); Console.WriteLine(a.x = 0, a.x); Console.WriteLine(b.x = 0, b.x); 输出是: a.x = 1b.x = 5 从这个例子例子可以看出,当一个结构被传递到一个方法时,被传递的只不过是一个副本,而一个类被传递时,被传递的是一个参考.所以a.x=输出的是1,不变,而b.x却变了. 还有的区别就是结构可以不用new来实例化,而类却要.如果你不用new来实例化一个结构,那么所有的字段将仍然处于未分配状态,直到所有的字段被初始化.和类一样,结构可以执行接口.更重要的是,结构没有继承性,一个结构不能从别的类继承,也不能是别的类的基类. C#进阶教程五什么是ADO(ActiveX Data Objects译作ActiveX数据对象),ADO是一个非常简单的思想,一种让你仅用一种方式去访问数据的思想.ADO不算一个新的思想,仅是采用现有的数据访问技术,将其融合起来.如果你不理解ADO,想一想ODBC吧!其实我们在搞ASP的时候,就用到了ADO,还记得吗,那个曾经被我们用过无数次的set conn=Server.CreateObject(ADODB.Connection)吗?是的,就是它.至于ADO的一些概念性的东西,请大家自行查阅资料,不过,其实不了解也没有关系,只把它想象成一个M$给我们的访问数据的工具吧! OK,下面的例子是以一个M$ ACCESS 2000的数据库为基础的,它的结构如下,表名是Categories,文件名是BugTypes.mdb ,赶快建一个吧: Category ID Category Name 1 Bugbash stuff 2 Appweek Bugs 3 .NET Reports 4 Internal support using System;using System.Data;using System.Data.OleDb; namespace 学习ADO public class MainClass public static void Main() / 设定好连接字符串和选择命令字符串: string strAccessConn = Provider=Microsoft.Jet.OLEDB.4.0;Data Source=BugTypes.MDB; string strAccessSelect = SELECT * FROM Categories; /file:/建立记录集,并把Categories这个表填进去 DataSet myDataSet = new DataSet(); myDataSet.Tables.Add(Categories); /file:/建立ADO实例: OleDbConnection myAccessConn = new OleDbConnection(strAccessConn); OleDbDataAdapter myAccessDataSetCmd = new OleDbDataAdapter(); /ADODataSetCommand myAccessDataSetCmd = new ADODataSetCommand(); myAccessDataSetCmd.SelectCommand = new OleDbCommand(strAccessSelect, myAccessConn); myAccessConn.Open(); try myAccessDataSetCmd.Fill(myDataSet, Categories); finally myAccessConn.Close(); try / 一个记录集可以包含多个表,我们把它们放到一个数组中: DataTable dta = myDataSet.Tables.All; foreach (DataTable dt in dta) Console.WriteLine(Found data table 0, dt.TableName); /file:/下面的两行程序展示了两种从一个记录集中得到这个数据集中的表格数的方法 Console.WriteLine(0 tables in data set, myDataSet.Tables.Count); Console.WriteLine(0 tables in data set, dta.Length); /file:/下面的几行程序说明了如何从一个记录集中依靠表格的名称来取得信息 Console.WriteLine(0 rows in Categories table, myDataSet.Tables.Rows.Count); /file:/列的信息是自动从数据库中得到的,所以我们可以用以下的代码: Console.WriteLine(0 columns in Categories table, myDataSet.Tables.Columns.Count); DataColumn drc = myDataSet.Tables.Columns.All; int i = 0; foreach (DataColumn dc in drc) /file:/打印出列的下标和列的名称和数据类型:/Console.WriteLine(Column name is 1, of type 2,i+ , dc.ColumnName, dc.DataType); DataRow dra = myDataSet.Tables.Rows.All; foreach (DataRow dr in dra) /file:/打印出CategoryID和CategoryName059: Console.WriteLine(CategoryName is 1, dr, dr); catch (Exception e) Console.WriteLine(Oooops. Caught an exception:n0, e.Message); 看起来,这个例子是有一些复杂的,只怪我例子选的不好,呵呵.不过,细细分析一下,还是可以理解的.我现在说一下这个例子中几个特别的东东.第一就是不象在ASP中,一个命令字符串被须被当作一个命令对象.020做的正是这个事情.注意,在015行有一个myDataSet.Tables.Add(Categories)语句,这并不是把数据库中的Categories这个表填进去,只不过是建一个空表,而025才是真的填充数据. 这个例子的输出是: Found data table Categories 1 tables in data set 1 tables in data set 4 rows in Categories table 2 columns in Categories table Column name is CategoryID, of type Int32 Column name is CategoryName, of type System.String CategoryName is Bugbash stuff CategoryName is Appweek Bugs CategoryName is .NET Reports CategoryName is Internal support C#进阶教程六现在我要说的是C#中的用户自定义转换(User-Defined Conversions),其中用到了前面说的struct的知识,就是结构呀,忘了吗?好,没忘就好.从我们以下的课程我们可以看到结构的用处(刚才我还在想它有什么用,呵呵).用class声明的是一个类,而用struct声明的可以看作是一个类型,对,就是像C#自带的int,short,long那样的类型了. C#中可以允许我们对结构(struct)和类(class)进行转换,所以我们可以在其中定义一些转换.但是,C#规定,所有的转换声明都必须在显示(explicit)和隐示(implicit)中选择一个.比方说,我们用这个语句的时候int a=10; System.Console.println(a):就用到了int的隐示的转换toString.如果是(String)a,就叫做显示.所以,显/隐之差就在于是否表现出来.大家现在肯定还是一头雾水,等到明天我把例子写出来再分析一下就清楚了,要熄灯了,我先走一步了! 下面给出例子,在这个例子中,一个名为RomanNumeral的类型被声明,然后对他实施了好几种转换.struct RomanNumeral public RomanNumeral(int value) this.value = value; static public implicit operator RomanNumeral(int value) return new RomanNumeral(value); static public explicit operator int(RomanNumeral roman) return roman.value; static public implicit operator string(RomanNumeral roman) return (Conversion not yet implemented); private int value; class Test static public void Main() RomanNumeral numeral; numeral = 10; Console.WriteLine(int)numeral); /显式地从numeral到int的转换: Console.WriteLine(numeral); /隐示地转换到string short s = (short)numeral; /显示地转换到int,然后显示地转换到short Console.WriteLine(s); Console.ReadLine(); 这个例子子的输出是: 10 Conversion not yet implemented 10 注意operator操作符,它是一个转换操作符.static public explicit operator int(RomanNumeral roman),记住这样的形式,它就代表了一个转换.再看第一个输出语句前面int这个转换被声明成了explicit,即显示地,所以,在使用这个转换时,必须用括号. 下面再给出一个例子,这个例子声明了两个结构,RomanNumeral和BinaryNumeral,然后在它们之间进行转换. struct RomanNumeral public RomanNumeral(int value) this.value = value; static public implicit operator RomanNumeral(int value) return new RomanNumeral(value); static public implicit operator RomanNumeral(BinaryNumeral binary) return new RomanNumeral(int)binary); static public explicit operator int(RomanNume

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论