iTePub电子图书论坛 » 程序开发设计 » [转贴]SUNWEN教程之----C#进阶

页: [1]

jinsheng04-12-13 09:57
[转贴]SUNWEN教程之----C#进阶

SUNWEN教程之----C#进阶
  (零)
  [email][email protected][/email]
  写在前面的话
  在写这些文章之前,我对C#一无所知.只从前辈那里听说了一些,说他很像JAVA.因为我
这段时间一直在看JAVA,结果什么明堂没看出来(只能怪我太笨:),其实我想还是没有实
践的机会),所以就很想换换口味.其实很早就听说了C#,想看一看这个东东,只是上M$的网
站一看,.NET的东东要一百多兆呢!看了就怕,何况全部下载下来,要费我一整张电话卡呢
?幸好我一个朋友先把.NET下载下来了,我拿了硬盘就跑过去拷过来了.一个SETUP.EXE,足
足有106M之巨.所以,我在此要特别感谢这位朋友阿KEN,没有他的帮助,就没有下面的文章
.
  写这篇文章的时候,我就有些害怕,怕自己水平不够,错误太多,挨别人骂.在写的过程中
,发现还是比较顺利的,因为这些跟原先的JAVA有很多相象的地方.而JAVA,很多前辈都有
很深的研究.不过,由于本人水平有限,错误之处在所难免,如果大家发现有什么错误之处
,还望指正,在下感激不尽!我的MAIL:[email protected].小弟先在此谢过了!
  以下的文章适用于有一些JAVA/C++编程经验的人,如果有JAVA的编程经验,那就更好了
,因为我在里面很多地方把C#与JAVA对比.如果你没有任何的编程序经验,可以到OICQ的主
页的社区去找另一系列的C#教程,那个可能更适合你.
  还有就是由于以下文章是在闲的时间写的,废话比较多,大家看了不要吐血哟@#$%^&*!
好了,下面开始吧!

jinsheng04-12-13 09:58
SUNWEN教程之----C#进阶
  (一)
  [email][email protected][/email]
  大家好,我是武汉华师的SUNWEN,我又回来了。五一大家都走了,SUNWEN还要在寝室
里奋战,呜呜。今天,我要向大家讲的是大家听说了好久的,又充满神密的语言:C#。

  今天刚从朋友那搞来了M$的.NET开发包,从M$的网站上下的,有106M,所以SUNWEN自然就
没有钱去下他了.话说今天早上六点.....(台下:快进入正题,笨蛋!又一双皮鞋飞了上来
,这已是第三双了!)是,我马上开始!
  刚拿到C#的参考时,我一看,这简直就是JAVA嘛!的确,跟外界说的一样,在表面上,C#和
JAVA非常地像,以致一个懂JAVA的人能够很快的掌握C#的结构.致于其内部的实现机理,那
我也不太清楚,只能与大家在学习中共同进步了,还希望大家多多捧场呀!
  好,为了给大家一个更清晰的感觉,我首先给大家一个例子,自然是HelloWorld(老土!)
.
  000: // HelloWorld\Hello1.cs
  001: public class Hello1
  002: {
  003: public static void Main()
  004: {
  005: System.Console.WriteLine("Hello, World!");
  006: }
  007: }
  它的输出结果是:
  Hello, World!
  有的朋友已经发现了,就是JAVA!只不过把System.out.prinln()改成了System.Consol
e.WriteLine()罢了!
  下面我们来分析一下这个程序,整个程序由一个public类(class)组成,里面必然有一
个public static void Main()这个方法,执行代码就在里面.System.Console.WriteLin
e("Hello, World!")这个语句的作用就是向控制台(Console)打印一行Hello,World!.很
简单吧!
  下面再来一个:
  000: // HelloWorld\Hello2.cs
  001: using System;
  002:
  003: public class Hello2
  004: {
  005: public static void Main()
  006: {
  007: Console.WriteLine("Hello, World!");
  008: }
  009: }
  这个程序用了一个using,其实它就等于JAVA里的import,就是引用一个包的意思.当引
用了这个包之后,在这个包中的Console类就不要指出全称了,只要Console.WriteLine()
就可以了,不必用System.Console.WriteLine()这么长了,省略了System了.
  例三,如下显示了如何显示命令行的参数
  000: // HelloWorld\Hello3.cs
  001: using System;
  002:
  003: public class Hello3
  004: {
  005: public static void Main(string[] args)
  006: {
  007: Console.WriteLine("Hello, World!");
  008: Console.WriteLine("You entered the following {0} command line argumen
ts:", args.Length );
  009: for (int i=0; i < args.Length; i++)
  010: {
  011: Console.WriteLine("{0}", args[i]);
  012: }
  013: }
  014: }
  可以看到,字符串数组args指的就是输入的参数.因为它是String类,所以都有Length方
法,所以可以有args.length来访问它的长度.然后用一个for循环来把它们显示出来.至于
循环这些东西,大都沿用了C的语法.
  例四,如果要一个返回值,那么可以像下面这样写,用return:
  000: // HelloWorld\Hello4.cs
  001: using System;
  002:
  003: public class Hello4
  004: {
  005: public static int Main(string[] args)
  006: {
  007: Console.WriteLine("Hello, World!");
  008: return 0;
  009: }
  010: }
  很简单吧!呵呵!对懂C或JAVA的人来说,比较好看懂,如果是VB或VBS的使用者,就有一些
困难了.呆呵!
  好了,看完了简单的例子,让我们来进入下一课吧!

jinsheng04-12-13 09:59
SUNWEN教程之----C#进阶
  (二)
  [email][email protected][/email]
  好了,I COME BACK,下面的代码显示了我们如何打印多个参数:
  000: // CommandLine\cmdline1.cs
  001: using System;
  002:
  003: public class CommandLine
  004: {
  005: public static void Main(string[] args)
  006: {
  007: Console.WriteLine("Number of command line parameters = {0}", args.Len
gth);
  008: for(int i = 0; i < args.Length; i++)
  009: {
  010: Console.WriteLine("Arg[{0}] = [{1}]", i, args[i]);
  011: }
  012: }
  013: }
  如果你的输入为:
  cmdline1 A B C
  那么它的输出为:
  Number of command line parameters = 3
  Arg[0] = [A]
  Arg[1] = [B]
  Arg[2] = [C]
  哈哈,看出了其中的秘密了吧!是的{0}是一个标记,它告诉系统,这里留下了给第0个参
数用,在程序中,这第0个参数就是i.因此,打印出来的就是Arg[0],面不是Arg[{0}]了,哈
哈!
  例二向大家展示了foreach这个语句的用法,其实在ASP中,这个经常用到:
  000: // CommandLine\cmdline2.cs
  001: using System;
  002:
  003: public class CommandLine2
  004: {
  005: public static void Main(string[] args)
  006: {
  007: Console.WriteLine("Number of command line parameters = {0}", args.Len
gth);
  008: foreach(string s in args)
  009: {
  010: Console.WriteLine(s);
  011: }
  012: }
  013: }
  很显然,args是一个数组,而且是字符型的.foreach的意思就是把其中的所有元素都循
环完.运行得出:
  >cmdline2 John Paul Mary
  Number of command line parameters = 3
  John
  Paul
  Mary
  好了,同志们,休息一下,我要睡觉了!88,下次再见!

jinsheng04-12-13 10:00
SUNWEN教程之----C#进阶
  (三)
  [email][email protected][/email]
  终于又到一个白天了,起床,伸个懒腰,又坐到了电脑前面.今天我要向大家讲的是C#的
数组(Arrays).C#中的数组和其它一些优秀的语言一样,也是从0开始计的,这从我们以前
的例子里可以看出来,也就是说,一个数组的第一个元素是a[0],而不是像VB的a(1).虽然
是这样,但是你还是要注意一些区别.
  在声明一个数组的时候,方括号必须跟在类型后面,而不能跟在变量名后面,如:
  int[] table; //不能写成int table[]
  这一点显然与JAVA是不同的,在JAVA中这样是可以的.
  还有就是在C#中你可以不指定数组的大小,这与C语言是不一样的.这使得你可以指定任
意长度的数组,如下:
  int[] numbers; // 它的长度是任意的
  当然,你也可以指定它的大小:
  int[10] numbers;//指定了一个长度为10的数组.
  在C#中,支持的数组包括:单维数组,多维数组和多重数组.它们的声明方法如下:
  单维数组:
  int[] numbers;
  多维数组:
  string[,] names;
  多重数组:
  byte[][] scores;
  声明一个数组并不代表已经建立了它.在C#中,所有的数组元素都是对象(倒!怎么跟JA
VA说得一样&*%$#@),所以在建立它之前,首先要将它实例化:
  单维数组:
  int[] numbers = new int[5];
  多维数组:
  string[,] names = new string[5,4];
  多重数组:
  byte[][] scores = new byte[5][];
  for (int x = 0; x < scores.Length; x++)
  {
   scores[x] = new byte[4];
  }
  呵呵,这有点奇怪吧,先不用理它,以后再说.
  我们同样可以建立更大的数组,比如一个三维数组:
  int[,,] buttons = new int[4,5,3];
  我们甚至可以混合多维数组和多重数组,下面的例子说明了这些:
  int[][,,][,] numbers;
  下面的例子展示了以上所有构建数组的方法:
  000: // Arrays\arrays.cs
  001: using System;
  002: class DeclareArraysSample
  003: {
  004: public static void Main()
  005: {
  006: // Single-dimensional array
  007: int[] numbers = new int[5];
  008:
  009: // Multidimensional array
  010: string[,] names = new string[5,4];
  011:
  012: // Array-of-arrays (jagged array)
  013: byte[][] scores = new byte[5][];
  014:
  015: // Create the jagged array
  016: for (int i = 0; i < scores.Length; i++)
  017: {
  018: scores[i] = new byte[i+3];
  019: }
  020:
  021: // Print length of each row
  022: for (int i = 0; i < scores.Length; i++)
  023: {
  024: Console.WriteLine("Length of row {0} is {1}", i, scores[i].Length);
  025: }
  026: }
  027: }
  它的输出是:
  Length of row 0 is 3
  Length of row 1 is 4
  Length of row 2 is 5
  Length of row 3 is 6
  Length of row 4 is 7
  在C#中数组的初始化可以在建立时就初始化,和JAVA和C一样,用的是{}.当然,很明显,
你的初始化值必须与你声明的数组类型一样,比如你定义了一个int类型的,你就不能给它
一个String,唉,JAVA看多了,在C#中,String应写为string,要不然,又要出错了.SUNWEN可
能在后面的课程中出现这样的错误,还望大家指正.呵呵!
  下面的例子说明了数组的初始化:
  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"};
  在C#中,数组的访问和C/C++/JAVA是一样的,下面的语句建立了一个数组,并将它的第五
个元素赋值为5:
  int[] numbers = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
  numbers[4] = 5;
  如果你没有C/JAVA/C++的编程经验,那么SUNWEN在此提醒,numbers[4]表示的是这个数
组的第五个元素,因为我在前面已经说过了,数组是从0开始计的,所以0,1,2,3,4正好是第
五个,所以....(台下:笨蛋,你以为我们不知道呀,快继续说!)
  下面的例子是关于多维数组的:
  int[,] numbers = { {1, 2}, {3, 4}, {5, 6}, {7, 8}, {9, 10} };
  numbers[1, 1] = 5;
  再次注意,C#中的所有数组都是对象(faint,D版),所以,你可以用访问对象的方法,来访
问数组.而System.Array就是数组的抽象.你可以参看文档来看Array类支持的方法.举个
例子来说吧,你可以用length属性来访问数组的长度.如下例:
  int[] numbers = {1, 2, 3, 4, 5};
  int LengthOfNumbers = numbers.Length;
  噢,好了,又完了一课,现在是北京时间上午9点16分,我要休息一下了!哈哈!待会见!

jinsheng04-12-13 10:01
SUNWEN教程之----C#进阶
  (四)
  [email][email protected][/email]
  大家好,我是武汉华师的SUNWEN.呵呵,下午好不容易有了时间出去玩了,到了归元寺.门
票十元,不算贵,SUNWEN照了好多像,用不了多久,就可以让大家看一看了.
  闲话少说,让我们进入正题.这次我要向大家讲的是C#中的属性.属性是什么呢,比如说
我是男的,男就是我的一人属性.我是一个大一的学生,大一也是我的一个属性.属性就是
一个对象的性质.很简单吧,呵呵!下面,我给出两个例子,第一个例子出明了如何声明一个
可以修改的属性,另一个例了建立了一个抽象的属性(Abstract),并且说明了如何在子类
中丢弃它.好,下面让我们开始吧.
  例子一:
  000: // Properties\person.cs
  001: using System;
  002: class Person
  003: {
  004: private string myName ="N/A";
  005: private int myAge = 0;
  006:
  007: // 声明一个字符型的属性Name
  008: public string Name
  009: {
  010: get
  011: {
  012: return myName;
  013: }
  014: set
  015: {
  016: myName = value;
  017: }
  018: }
  019:
  020: // 声明一个int型的Age属性
  021: public int Age
  022: {
  023: get
  024: {
  025: return myAge;
  026: }
  027: set
  028: {
  029: myAge = value;
  030: }
  031: }
  032:
  033: public override string ToString()
  034: {
  035: return "Name = " + Name + ", Age = " + Age;
  036: }
  037:
  038: public static void Main()
  039: {
  040: Console.WriteLine("Simple Properties");
  041:
  042: // 建立一个Person的实例
  043: Person person = new Person();
  044:
  045: //打印出它的属性
  046: Console.WriteLine("Person details - {0}", person);
  047:
  048: // 对属性进行一些设置
  049: person.Name = "Joe";
  050: person.Age = 99;
  051: Console.WriteLine("Person details - {0}", person);
  052:
  053: // 增加年龄
  054: person.Age += 1;
  055: Console.WriteLine("Person details - {0}", person);
  056: }
  057: }
  这个例子的输出是:
  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,又差点犯错!)方法.在33行
,我们可以看到有这个方法的影子,override这个关键字大概就是覆盖父类的方法吧,这是
不是有点多余?我们可以看到,一个对象的属性的设置是通过一个get()和set()组合来完
成的,当然,还有一个value这个东东.补充一下,你还可以控制一个属性的读/写权限,只是
把get()和set()简单地去掉就可以了,比如你不要写的属性,就不要set()就可以了,如果
你不要读,就不要get()吧.总得感觉,C#在这点上没有JAVA来的灵活(完了,又要被盖痴打
了!).
  第二个例子:
  这个例子说明了如何建立抽象的属性(Abstract),什么是抽象的属性呢,所谓的抽象的
属性呢,就是....(唉,每次废话都这么多!FT) 一个抽象类并不提供执行属性存取程序,并
且,他可以在子类中被忽略.下面的例子有三个文件,你要分别编译它们才能得到结果,它
们是:
  abstractshape.cs: Shape类,包含一个Area抽象属性
  shapes.cs: Shape的子类
  shapetest.cs: 显示程序.
  要编译这些程序,运行:csc abstractshape.cs shapes.cs shapetest.cs就可以了.运
行完之后,它会产生shapetest.exe这个可执行程序.
  000: // Properties\abstractshape.cs
  001: using System;
  002:
  003: public abstract class Shape
  004: {
  005: private string myId;
  006:
  007: public Shape(string s)
  008: {
  009: Id = s; // 这句调用了Id属性的set构建器
  010: }
  011:
  012: public string Id
  013: {
  014: get
  015: {
  016: return myId;
  017: }
  018:
  019: set
  020: {
  021: myId = value;
  022: }
  023: }
  024:
  025: public abstract double Area
  026: {
  027: get;
  028: }
  029:
  030: public override string ToString()
  031: {
  032: return Id + " Area = " + double.Format(Area, "F");
  033: }
  034: }
  看这个程序, 实际上非常地简单,当这个类对的对象被建立时,初始化部分为007-010,
它把建立对象的参数s给了Id这个属性.然后进行了上一个例子的操作.实际上,我们可以
把抽象属性与JAVA中的接口(Interface)相比,它们只提拱一个方法的名称,而不提供这个
方法的内容.就像Area这个抽象属性,有一个get,但是它并没有指定get方法(也许它不能
称之为方法)里的内容,即要get做什么事情. 这个事情,由它的子类来做.
  第二个文件:在这个文件中,一个类覆盖了(override)了Area属性.
  000: // Properties\shapes.cs
  001: public class Square : Shape
  002: {
  003: private int mySide;
  004:
  005: public Square(int side, string id) : base(id)
  006: {
  007: mySide = side;
  008: }
  009:
  010: public override double Area
  011: {
  012: get
  013: {
  014: return mySide * mySide;
  015: }
  016: }
  017: }
  018:
  019: public class Circle : Shape
  020: {
  021: private int myRadius;
  022:
  023: public Circle(int radius, string id) : base(id)
  024: {
  025: myRadius = radius;
  026: }
  027:
  028: public override double Area
  029: {
  030: get
  031: {
  032: return myRadius * myRadius * System.Math.PI;
  033: }
  034: }
  035: }
  036:
  037: public class Rectangle : Shape
  038: {
  039: private int myWidth;
  040: private int myHeight;
  041:
  042: public Rectangle(int width, int height, string id) : base(id)
  043: {
  044: myWidth = width;
  045: myHeight = height;
  046: }
  047:
  048: public override double Area
  049: {
  050: get
  051: {
  052: return myWidth * myHeight;
  053: }
  054: }
  055: }
  这个例子就有些让我们一头雾水了,:是干什么的,好象是继承,相当于JAVA中的extend
s吧.我想是的.我们先看一看吧.
  下面的第三个文件就是一个测试文件了,很简单,大家看一看.
  000: // Properties\shapetest.cs
  001: public class TestClass
  002: {
  003: public static void Main()
  004: {
  005: Shape[] shapes =
  006: {
  007: new Square(5, "Square #1"),
  008: new Circle(3, "Circle #1"),
  009: new Rectangle( 4, 5, "Rectangle #1")
  010: };
  011:
  012: System.Console.WriteLine("Shapes Collection");
  013: foreach(Shape s in shapes)
  014: {
  015: System.Console.WriteLine(s);
  016: }
  017:
  018: }
  019: }
  从这个例子上看,:这个符号的确是extends的意思,就是继承.继承是什么意思,说白了
,就是生孩子的意思.比如下面一句sunwenson extends sunwen,这名就是说sunwenson这
个类继承了sunwen,sunwenson这个类有sunwen类的所有东西,同时可以添加和删除sunwe
n中的一些东西.就这么简单,但是这是现代软件发展的一项重要技术,因为它可以使软件
的重用性大大提高.唉,这些就只有大三大四的人说了,我就没资格了.呵呵.
  这个程序的输出是:
  Shapes Collection
  Square #1 Area = 25.00
  Circle #1 Area = 28.27
  Rectangle #1 Area = 20.00
  完了,这一节又完了.要理解这一节,有一定的难度, 特别对那些没有JAVA或C++编程经
验的朋友.不过不要害怕,鼓起勇气学下去,一定会有所收获的. 我也要休息一下了,嘿嘿
,早饭还没有吃呢

jinsheng04-12-13 10:03
SUNWEN教程之----C#进阶
  (五)
  [email][email protected][/email]
  大家好,我是武汉华师的SUNWEN.我回来了.现在是五月二号下午3:20.我刚从电脑城回
来,买了一版D版的MP3.呜,湖北的同学都回去了,尤其是武汉的,跑得特别快,真是可恨.剩
下我一个孤零零的福建佬,没事做,只好一个人听音乐,真是惨!幸好这音乐还比较好听,呵
呵,其实SUNWEN一点音乐细胞也没有.
  言归正传,我现在要说的是库(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:指出要引用的库,如果不是在当前目录下,必须要指出其的完整路径
.
  下面我就把这几个文件的代码写在下面:
  000: // Libraries\Factorial.cs
  001: using System;
  002:
  003: namespace Functions
  004: {
  005: public class Factorial
  006: {
  007: public static int Calc(int i)
  008: {
  009: return((i <= 1) ? 1 : (i * Calc(i-1)));
  010: }
  011: }
  012: }
  这是Factorial.cs这个文件的代码.在003行中,namespace的意思是名字空间,据M$的介
绍,库必须根据它的名字空间打包,以使.NET能够正确地载入你的类.
  下面是DigitCounter.cs这个文件的内容:
  000: // Libraries\DigitCounter.cs
  001: using System;
  002:
  003: namespace Functions
  004: {
  005: public class DigitCount
  006: {
  007: public static int NumberOfDigits(string theString)
  008: {
  009: int count = 0;
  010: for ( int i = 0; i < theString.Length; i++ )
  011: {
  012: if ( Char.IsDigit(theString[i]) )
  013: {
  014: count++;
  015: }
  016: }
  017:
  018: return count;
  019: }
  020: }
  021: }
  注意,这个例子中的namespace应与第一个的一致,因为它们是同一个库中的.NumberOf
Digits方法计算了参数中的数字的个数.
  第三个文件是FunctionClient.cs
  我们知道,一个库一旦建立,就可以被别的类利用(废话,要不然怎么叫库呢?).下面的C
#程序就利用了我们刚才建立的库中的类.
  000: // Libraries\FunctionClient.cs
  001: using System;
  002: using Functions;
  003: class FunctionClient
  004: {
  005: public static void Main(string[] args)
  006: {
  007: Console.WriteLine("Function Client");
  008:
  009: if ( args.Length == 0 )
  010: {
  011: Console.WriteLine("Usage: FunctionTest ... ");
  012: return;
  013: }
  014:
  015: for ( int i = 0; i < args.Length; i++ )
  016: {
  017: int num = Int32.Parse(args[i]);
  018: Console.WriteLine(
  019: "The Digit Count for String [{0}] is [{1}]",
  020: args[i],
  021: DigitCount.NumberOfDigits(args[i]));
  022: Console.WriteLine(
  023: "The Factorial for [{0}] is [{1}]",
  024: num,
  025: Factorial.Calc(num) );
  026: }
  027: }
  028: }
  在002行中,一个using Functions指明了引用Functions.DLL这个类.
  如果我们在命令行中键入如下命令,就可以看到输出:
  FunctionTest 3 5 10
  输出:
  Function Client
  The Digit Count for String [3] is [1]
  The Factorial for [3] is [6]
  The Digit Count for String [5] is [1]
  The Factorial for [5] is [120]
  The Digit Count for String [10] is [2]
  The Factorial for [10] is [3628800]
  注意:当你运行这个.EXE文件时,它引用的DLL文件可以是在当前目录,子目录,或是COR
PATH这个环境变量.CORPATH这个环境变量是在.NET环境中的类路径,用来指引系统寻找类
.说白了,就是JAVA中的CLASSPATH,明白了吧,呵呵.
  好了,又完了一篇,今天的任务完成了,可以休息了.唉,有什么好玩的呢?

jinsheng04-12-13 10:06
SUNWEN教程之----C#进阶
  (六)
  [email][email protected][/email]
  大家好,我是武汉华师的SUNWEN.现在是五月二号晚上19:27,由于闲着没事干,所有又写
起来了.昨天照了十几张相,待会可以去取了,不知照片中的我是不是很帅,呵呵!现在我耳
边正听着2000欧洲杯的曲子,所以比较激动.唉,身为我们院2000级足球队长的我,已经很
久没有踢球了!
  现在我要说的是C#中的版本处理.其实这是任何一个软件必须要考虑的问题.每个软件
都不只一个版本(除了我写的以外),因此版本处理显得非常地重要.JAVA很好地处理了这
个问题,而我个人认为C#借鉴了JAVA的处理方法,所以,也做得很好.
  在C#中,如果你在声明一个方法的时候用了virtual这个关键字,那么,在派生类中,你就
可以使用override或者new关键字来弃用它或是忽略它.如果你在父类中用了virtual这个
关键字,而在其派生类中又没有用override或new关键字,而直接引用一个同名方法的话,
编译器将会报错,并将以new方式,即忽略派生类中的方法的方式来运行.下面的例子可以
帮助你来理解:
  000: // Versioning\versioning.cs
  001: public class MyBase
  002: {
  003: public virtual string Meth1()
  004: {
  005: return "MyBase-Meth1";
  006: }
  007: public virtual string Meth2()
  008: {
  009: return "MyBase-Meth2";
  010: }
  011: public virtual string Meth3()
  012: {
  013: return "MyBase-Meth3";
  014: }
  015: }
  016:
  017: class MyDerived : MyBase
  018: {
  019: public override string Meth1()
  020: {
  021: return "MyDerived-Meth1";
  022: }
  023: public new string Meth2()
  024: {
  025: return "MyDerived-Meth2";
  026: }
  027: public string Meth3() // 系统在这里将会有一个警告,并且将会隐藏方法Met
h3()
  028:
  029:
  030: {
  031: return "MyDerived-Meth3";
  032: }
  033:
  034: public static void Main()
  035: {
  036: MyDerived mD = new MyDerived();
  037: MyBase mB = (MyBase) mD;
  038:
  039: System.Console.WriteLine(mB.Meth1());
  040: System.Console.WriteLine(mB.Meth2());
  041: System.Console.WriteLine(mB.Meth3());
  042: }
  043: }
  输出:
  MyDerived-Meth1
  MyBase-Meth2
  MyBase-Meth3
  可以很明显地看出来,后两个new关键字的输出是父类中的方法的输出,所以可以看出,
new这个关键字的作用是如果在以前的版本中有这个方法,就沿用以前的方法,而不用我现
在方法内容.而virtual的方法的作用正好相反,它的作用是如果在父类中有这样一个方法
,则用我现在写的方法内容,让以前的滚蛋!不过,这里用new好象不太好,让人误解(糟了,
盖痴又要打我了!&*%$#@).
  如果你把第037行去掉,把039-041中的mB全部改为mD,输出又变为:
  MyDerived-Meth1
  MyDerived-Meth2
  MyDerived-Meth3
  这又说明了什么呢,说明了派生类的对象只有在被父类重塑的时候,override和new关键
字才会生效.呵呵,这样说的确有点难以理解,大家只有自己动手,才能搞清楚这其中的机
关,所谓"实践是检验C#的唯一标准",哈哈!
  在C#中,你可以自由地为在派生类中为加入一个方法,或者覆盖父类的方法,如下所示,
非常地简单:
  class Base {}
  class Derived: Base
  {
   public void F() {}
  }
  和:
  class Base
  {
   public void F() {}
  }
  class Derived: Base
  {
   public void F() {}
  }
  好了,这一节又完了,音乐还没完,但是我真的要休息了,明天见!

jinsheng04-12-13 10:08
大家好,我是武汉华师的SUNWEN.现在是五月四日中午,昨天一天由于在搞自己的技术
网站,叫"鬼子山技术站",(嘿嘿,有点恐怖吧!)所以没有写.等这个站建好后,还要大家多
多捧场啊,我们这个站主要是面向教育网的,因为服务器就在教育网内.
  好了,言归正传.我要说的是C#中的结构(struct),注意,我在这里说的结构不是指的C#
的语言结构.这里所说的是一种与类(class)相对的东西,下面我就与类相对比,来说一说
这个struct.
  下面的这个例子讲述了如何建立一个具有属性,方法和一个字段的结构.并讲述如何使
用他.
  000: // Structs\struct1.cs
  001: using System;
  002: struct SimpleStruct
  003: {
  004: private int xval;
  005: public int X
  006: {
  007: get {
  008: return xval;
  009: }
  010: set {
  011: if (value < 100)
  012: xval = value;
  013: }
  014: }
  015: public void DisplayX()
  016: {
  017: Console.WriteLine("The stored value is: {0}", xval);
  018: }
  019: }
  020:
  021: class TestClass
  022: {
  023: public static void Main()
  024: {
  025: SimpleStruct ss = new SimpleStruct();
  026: ss.X = 5;
  027: ss.DisplayX();
  028: }
  029: }
  这个例子的输出是:
  The stored value is: 5
  从上面的例子中我们可以看到结构和类似乎是一样的.的确,如果你用类去重亲写这个
程序,结果是一样的.但是,很明显,两个一样的东西是不可能一起出现的. 结构(struct)
是值(value)型的,而类是参考型的.这样,你就可以用结构建立像内建类型那样的对象了
.
  还有就是如果你用一个new关键字建立一个类的实例的时候,它是以堆(heap)来分配的
,而用new来建立一个结构的的实例的时候,它是以栈(stack)来分配.这会给我们提高很多
性能(M$说的).好了,让我们再来看下面的例子吧:
  000: // Structs\struct2.cs
  001: using System;
  002:
  003: class TheClass
  004: {
  005: public int x;
  006: }
  007:
  008: struct TheStruct
  009: {
  010: public int x;
  011: }
  012:
  013: class TestClass
  014: {
  015: public static void structtaker(TheStruct s)
  016: {
  017: s.x = 5;
  018: }
  019: public static void classtaker(TheClass c)
  020: {
  021: c.x = 5;
  022: }
  023: public static void Main()
  024: {
  025: TheStruct a = new TheStruct();
  026: TheClass b = new TheClass();
  027: a.x = 1;
  028: b.x = 1;
  029: structtaker(a);
  030: classtaker(b);
  031: Console.WriteLine("a.x = {0}", a.x);
  032: Console.WriteLine("b.x = {0}", b.x);
  033: }
  034: }
  这个例子的输出是:
  a.x = 1b.x = 5
  从这个例子例子可以看出,当一个结构被传递到一个方法时,被传递的只不过是一个副
本,而一个类被传递时,被传递的是一个参考.所以a.x=输出的是1,不变,而b.x却变了.
  还有的区别就是结构可以不用new来实例化,而类却要.如果你不用new来实例化一个结
构,那么所有的字段将仍然处于未分配状态,直到所有的字段被初始化.和类一样,结构可
以执行接口.更重要的是,结构没有继承性,一个结构不能从别的类继承,也不能是别的类
的基类.
  例三:
  interface IImage
  {
   void Paint();
  }
  struct Picture : IImage
  {
   public void Paint()
   {
   // painting code goes here
   }
   private int x, y, z; // other struct members
  }
  好了,关于结构我就讲到这了,以后还会讲到的.

jinsheng04-12-13 10:11
大家好,我是武汉华师的SUNWEN,今天Zzz....(快醒醒!啪!..啪!倒,叫我起来也不要用
皮鞋来打嘛@#$%&*).现在是五月四号晚上19:33,我好想睡觉.只好打开音乐来提神了!
  这一节我要讲的是大家非常关心的,肯定也是非常感兴趣的部分.嘿嘿,也是我写教程最
拿手的部分----ADO数据库访问.想到这,我就想起我在去年写的"访问数据库"系列文章,
嘿嘿!所以呢,如果你觉得对记录集之类的东西比较难理解的话,我推荐你先看一看我的那
几篇文章.好了,让我们开始吧!
  什么是ADO(ActiveX Data Objects译作ActiveX数据对象),ADO是一个非常简单的思想
,一种让你仅用一种方式去访问数据的思想.ADO不算一个新的思想,仅是采用现有的数据
访问技术,将其融合起来.如果你不理解ADO,想一想ODBC吧!其实我们在搞ASP的时候,就用
到了ADO,还记得吗,那个曾经被我们用过无数次的set conn=Server.CreateObject("ADO
DB.Connection")吗?是的,就是它.至于ADO的一些概念性的东西,请大家自行查阅资料,不
过,其实不了解也没有关系,只把它想象成一个M$给我们的访问数据的工具吧!
  OK,下面的例子是以一个M$ ACCESS 2000的数据库为基础的,它的结构如下,表名是Cat
egories,文件名是BugTypes.mdb ,赶快建一个吧:
  Category ID Category Name
  1 Bugbash stuff
  2 Appweek Bugs
  3 .NET Reports
  4 Internal support
  好的,我先把所有的程序都写出来,然后我们来一句一句的品尝:
  000: // ADO\adosample.cs
  001: using System;
  002: using System.Data;
  003: using System.Data.ADO;
  004:
  005: public class MainClass
  006: {
  007: public static void Main ()
  008: {
  009: // 设定好连接字符串和选择命令字符串010: string strAccessConn = "Provi
der=Microsoft.Jet.OLEDB.4.0;Data Source=BugTypes.MDB";
  011: string strAccessSelect = "SELECT * FROM Categories";
  012:
  013: //建立记录集,并把Categories这个表填进去
  014: DataSet myDataSet = new DataSet();
  015: myDataSet.Tables.Add("Categories");
  016:
  017: //建立ADO实例018: ADOConnection myAccessConn = new ADOConnection(strA
ccessConn);
  019: ADODataSetCommand myAccessDataSetCmd = new ADODataSetCommand();
  020: myAccessDataSetCmd.SelectCommand = new ADOCommand(strAccessSelect,myA
ccessConn);
  021:
  022: myAccessConn.Open();
  023: try
  024: {
  025: myAccessDataSetCmd.FillDataSet(myDataSet,"Categories");
  026: }
  027: finally
  028: {
  029: myAccessConn.Close();
  030: }
  031:
  032: try
  033: {
  034: // 一个记录集可以包含多个表,我们把它们放到一个数组中035: DataTable[]
dta = myDataSet.Tables.All;
  036: foreach (DataTable dt in dta)
  037: {
  038: Console.WriteLine("Found data table {0}", dt.TableName);
  039: }
  040:
  041: //下面的两行程序展示了两种从一个记录集中得到这个数据集中的表格数的方法

  042: Console.WriteLine("{0} tables in data set", myDataSet.Tables.Count);
  043: Console.WriteLine("{0} tables in data set", dta.Length);
  044: //下面的几行程序说明了如何从一个记录集中依靠表格的名称来取得信息
  045: Console.WriteLine("{0} rows in Categories table", myDataSet.Tables["C
ategories"].Rows.Count);
  046: //列的信息是自动从数据库中得到的,所以我们可以用以下的代码047: Console
.WriteLine("{0} columns in Categories table", myDataSet.Tables["Categories"]
.Columns.Count);
  048: DataColumn[] drc = myDataSet.Tables["Categories"].Columns.All;
  049: int i = 0;
  050: foreach (DataColumn dc in drc)
  051: {
  052: //打印出列的下标和列的名称和数据类型053: Console.WriteLine("Column na
me[{0}] is {1}, of type {2}",i++ , dc.ColumnName, dc.DataType);
  054: }
  055: DataRow[] dra = myDataSet.Tables["Categories"].Rows.All;
  056: foreach (DataRow dr in dra)
  057: {
  058: //打印出CategoryID和CategoryName059: Console.WriteLine("CategoryName[
{0}] is {1}", dr[0], dr[1]);
  060: }
  061: }
  062: catch (Exception e)
  063: {
  064: Console.WriteLine("Oooops. Caught an exception:\n{0}", e.Message);
  065: }
  066: }
  067: }
  看起来,这个例子是有一些复杂的,只怪我例子选的不好,呵呵.不过,细细分析一下,还
是可以理解的.我现在说一下这个例子中几个特别的东东.第一就是不象在ASP中,一个命
令字符串被须被当作一个命令对象.020做的正是这个事情.注意,在015行有一个myDataS
et.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[0] is CategoryID, of type Int32
  Column name[1] is CategoryName, of type System.String
  CategoryName[1] is Bugbash stuff
  CategoryName[2] is Appweek Bugs
  CategoryName[3] is .NET Reports
  CategoryName[4] is Internal support
  好了,就说到这吧,SUNWEN真是想睡了,什么音乐都不管用了,呵呵.这个例子还真要花大
力气才能完全理解.O.K.886!

jinsheng04-12-13 10:13
大家好,我是SUNWEN,现在是五月四号23:15,再过十五分钟就要熄灯了.所以要抓紧时间
,先开个头,明天继续.
  现在我要说的是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,就叫做显示.所以,显/隐之差就
在于是否表现出来.大家现在肯定还是一头雾水,等到明天我把例子写出来再分析一下就
清楚了,要熄灯了,我先走一步了!
  喔~~~~~终于起来了,五月五日8:45.下面给出例子,在这个例子中,一个名为RomanNum
eral的类型被声明,然后对他实施了好几种转换.
  000: // UserConversions\conversion.cs
  001: using System;
  002:
  003: struct RomanNumeral
  004: {
  005: public RomanNumeral(int value)
  006: {
  007: this.value = value;
  008: }
  009: static public implicit operator RomanNumeral(int value)
  010: {
  011: return new RomanNumeral(value);
  012: }
  013: static public explicit operator int(RomanNumeral roman)
  014: {
  015: return roman.value;
  016: }
  017: static public implicit operator string(RomanNumeral roman)
  018: {
  019: return("Conversion not yet implemented");
  020: }
  021: private int value;
  022: }
  023:
  024: class Test
  025: {
  026: static public void Main()
  027: {
  028: RomanNumeral numeral;
  029:
  030: numeral = 10;
  031:
  032: // 显式地从numeral到int的转换033: Console.WriteLine((int)numeral);
  034:
  035: // 隐示地转换到string036: Console.WriteLine(numeral);
  037:
  038: // 显示地转换到int,然后显示地转换到short040: short s = (short)numeral
;
  041:
  042: Console.WriteLine(s);
  043:
  044: }
  045: }
  这个例子子的输出是:
  10
  Conversion not yet implemented
  10
  注意009和013的operator操作符,它是一个转换操作符.static public explicit ope
rator int(RomanNumeral roman),记住这样的形式,它就代表了一个转换.再看第033行,
因为在前面int这个转换被声明成了explicit,即显示地,所以,在使用这个转换时,必须用
括号.
  下面再给出一个例子,这个例子声明了两个结构,RomanNumeral和BinaryNumeral,然后
在它们之间进行转换.
  000: // UserConversions\structconversion.cs
  001: using System;
  002:
  003: struct RomanNumeral
  004: {
  005: public RomanNumeral(int value) { this.value = value; }
  006: static public implicit operator RomanNumeral(int value)
  007: {return new RomanNumeral(value);}
  008: static public implicit operator
  009: RomanNumeral(BinaryNumeral binary)
  010: {return new RomanNumeral((int)binary);}
  011: static public explicit operator int(RomanNumeral roman)
  012: {return roman.value;}
  013: static public implicit operator string(RomanNumeral roman)
  014: {return("Conversion not yet implemented");}
  015: private int value;
  016: }
  017:
  018: struct BinaryNumeral
  019: {
  020: public BinaryNumeral(int value) {this.value = value;}
  021:
  022: static public implicit operator BinaryNumeral(int value)
  023: {return new BinaryNumeral(value);}
  024: static public implicit operator string(BinaryNumeral binary)
  025: {return("Conversion not yet implemented");}
  026: static public explicit operator int(BinaryNumeral binary)
  027: {return(binary.value);}
  028:
  029: private int value;
  030: }
  031:
  032: class Test
  033: {
  034: static public void Main()
  035: {
  036: RomanNumeral roman;
  037: roman = 10;
  038: BinaryNumeral binary;
  039: binary = (BinaryNumeral)(int)roman;
  040: roman = binary;
  041: Console.WriteLine((int)binary);
  042: Console.WriteLine(binary);
  043: }
  044: }
  这个例子的输出是:
  10
  Conversion not yet implemented
  注意,第039行并没有直接由RomanNumeral转化成BinaryNumeral,因为没有直接的转换
提供.所以先把RomanNumeral转换成int,再转成BinaryNumeral.其余的东西跟上面的例子
是一样的(至少我这么认为),如果上面的例子理解了,下面的就好了.
  OK,又完了一节,学了这么多,大家有什么感觉呢,欢迎和我交流,[email][email protected][/email]

jinsheng04-12-13 10:14
大家好,我是SUNWEN.今天下午得知,晚上要去当"更夫".呵呵,我们这个学校很是奇怪
,要叫我们轮流去通宵巡逻,从晚上10:30到早上6:00.我有一个物理系的朋友,上次在田家
炳楼门前找了一个宣传板,垫在下面就睡了一觉,听了笑死我了!哈哈!
  现在我想说的是C#中的容器.这是一个非常重要的话题,因为不管你写什么样的程序,你
都不能不与容器打交道.什么是容器呢(倒!).容器就是可以容纳东西的东西(再倒!),在C
#和JAVA这种面向对象的编程语言中,容器就被称为可以容纳对象的东东,不是说"一切都
是对象吗?"以前,我一个搞C++的程序员朋友告诉我,JAVA中的容器太好用了,比C++好用多
了.而作为JAVA的后来者的C#毫无疑问,它的容器功能肯定也是很强大的.
  foreach语句是遍历容器的元素的最简单的方法.我们可以用System.Collections.IEn
umerator类和System.Collections.IEnumerable接口来使用C#中的容器,下面有一个例子
,功能是字符串分割器.
  000: // CollectionClasses\tokens.cs
  001: using System;
  002: using System.Collections;
  003:
  004: public class Tokens : IEnumerable
  005: {
  006: private string[] elements;
  007:
  008: Tokens(string source, char[] delimiters)
  009: {
  010: elements = source.Split(delimiters);
  011: }
  012:
  013: //引用IEnumerable接口014:
  015: public IEnumerator GetEnumerator()
  016: {
  017: return new TokenEnumerator(this);
  018: }
  019:
  020:
  021:
  022: private class TokenEnumerator : IEnumerator
  023: {
  024: private int position = -1;
  025: private Tokens t;
  026:
  027: public TokenEnumerator(Tokens t)
  028: {
  029: this.t = t;
  030: }
  031:
  032: public bool MoveNext()
  033: {
  034: if (position < t.elements.Length - 1)
  035: {
  036: position++;
  037: return true;
  038: }
  039: else
  040: {
  041: return false;
  042: }
  043: }
  044:
  045: public void Reset()
  046: {
  047: position = -1;
  048: }
  049:
  050: public object Current
  051: {
  052: get
  053: {
  054: return t.elements[position];
  055: }
  056: }
  057: }
  058:
  059: // 测试060:
  061: static void Main()
  062: {
  063: Tokens f = new Tokens("This is a well-done program.", new char[] {' '
,'-'});
  064: foreach (string item in f)
  065: {
  066: Console.WriteLine(item);
  067: }
  068: }
  069: }
  这个例子的输出是:
  This
  is
  a
  well
  done
  program.
  好了,这一节就说到这了.现在环境不太好,旁边一大帮同学在看VCD,不好搞.

jinsheng04-12-13 10:16
OK,我又回来了,前面写了那么多,跟JAVA的对比也够多了,现在我就用我自己试验的
例子,来看一看C#这个被称为JAVA#的新一代编程语言到底与JAVA有多大的区别.
  首先我们建立一个C#的程序文件cs1.cs,然后再建立一个JAVA的源程序文件cs1.java.
它们的内容分别是:
  cs1.cs:
  using System;
  public class cs1{
   public static void Main(){
   Console.WriteLine("i am sunwen!");
   sunwen mySunwen=new sunwen();
   Console.WriteLine(mySunwen.name);
   }
  }
  class sunwen{
   public String name="chenbin!";
  }
  cs1.java:
  import System.*;
  public class cs1{
   public static void main(String args[]){
   System.out.println("i am sunwen,how are you!");
   sunwen mySunwen=new sunwen();
   System.out.println(mySunwen.name);
   }
  }
  class sunwen{
   String name="chenbin!";
  }
  OK,让我们来运行一下这两个程序.在编译过程中我们发现,C#的速度的确比JAVA要快好
多.(不是说M$的好话)其实,两个程序的输出是一样的,都是:
  i am sunwen!
  chenbin!
  有一个重要的区别就是看有一行是publc String name="chenbin!",而在JAVA中却是S
tring name="chenbin!".如果我们在cs1.cs中把这个public去掉,就会产生错误,因为在
C#中,不用任何范围修饰符时,默认的是protect,因而不能在类外被访问.
  这是一个重要的区别之一.还有就是:如果我们把cs1.cs这个C#程序中的一句public c
lass cs1改为public class cs2,存盘,再编译,可以看到,程序正常运行.而在JAVA中,这
显然不行,因为JAVA规定,在一个文件中只能有一个public类,而且这个类的名称必须与文
件名一模一样.这又是一个区别,在C#中,它是以Main方法来定位入口的.如果一个程序中
没有一个名为Main的方法,就会出"找不到入口的错误".不要把Main写成main哟,嘻嘻,我
经常犯这样的错误.
  好了,就说到这了,以后再遇到再说吧!

littlefatso04-12-21 12:21
说实话,并不是很好,现在很多C#的书都讲的不错,认真选一本在Amazon有4星以上评价的书就足够了


查看完整版本: [转贴]SUNWEN教程之----C#进阶


Powered by Discuz! Archiver 4.1.0  © 2001-2006 Comsenz Inc.
Processed in 0.030827 second(s), 2 queries