简述:C#中的库(libraries) ~*h)`uM
言归正传,我现在要说的是库(libraries),和大家一起学习如何用C#建立一个DLL文件.说起DLL,肯定是无人不知,无人不晓,这个WINDOWS的典型代表,同时也经常是大家功击的对象.呵呵,不管怎么样,学还是要学的.我们下面就开始,如何用命令行方式将一个C#程序编译成DLL,和如何在客户端使用他. nS$4[!0
这个例子包括两个文件,一个是Factorial.cs,作用是计算一个数字的阶乘.还有一个是DigitCounter.cs,作用是计算传过来的字符串参数中的数字的数目. TS=%iMa
我们可以这样来建立库,在命令行方式下这样做: zk70D_}L
csc /target:library /out:Functions.dll Factorial.cs DigitCounter.cs vyc<RjS_x
下面讲一下各个参数的用法: d<?Zaehe\
/target:library:向系统指出输出的是一个DLL库,而不是一个EXE的可执行文件. :OU(fz]
/out:Functions.dll:指定输出的DLL的文件名,即Functions.dll,一般地,如果你省略了第一个参数,那么默认的文件名将是第一个文件的文件名,即Factorial.dll. T:Q+ Z }v+
下面我们再来建立一个文件,即使用这个库的文件,叫客户端文件,FunctionClient.cs.建立好后,用下面的语名编译: "nJMS6HJ[
csc /out:FunctionTest.exe /R:Functions.DLL FunctionClient.cs 49/2E@G4.
下面说一下这个编译语句的用法: dG3?(}p+
/out:FunctionTest.exe:指出输出的文件名是FunctionTest.exe $hJ 4=F
/R:Functions.DLL:指出要引用的库,如果不是在当前目录下,必须要指出其的完整路径. ]nV_K}!w
下面我就把这几个文件的代码写在下面: OvdBUcp[
000: // Libraries\Factorial.cs LVP6vs
001: using System; tvJl-&'N
002: #\F8(lZ
003: namespace Functions 9[{q5
004: { F9w2+z.
005: public class Factorial o}36bi{
006: { z4.|N
007: public static int Calc(int i) tm34Z''.>
008: { mFpj@=^_G
009: return((i <= 1) ? 1 : (i * Calc(i-1))); y54RD/`-
010: } oMn'{+(w
011: } 8f?o?c|
012: } ~Gg19x.#uW
这是Factorial.cs这个文件的代码.在003行中,namespace的意思是名字空间,据M$的介绍,库必须根据它的名字空间打包,以使.NET能够正确地载入你的类. `h'Ab63
下面是DigitCounter.cs这个文件的内容: %,N-M]Jf
000: // Libraries\DigitCounter.cs "}uu-5]3
001: using System; T?n [1%K
002: P'5Lu
003: namespace Functions C>l (4*S
004: { ]w)uo4<^J
005: public class DigitCount (s1iYK
006: { F":dS-u&L
007: public static int NumberOfDigits(string theString) GYT0zMMf
008: { y#ON=8l
009: int count = 0; _n*gj-
010: for ( int i = 0; i < theString.Length; i++ ) '+|uv7|+v
011: { <+ <o
X"I
012: if ( Char.IsDigit(theString) ) /KiaLS
013: { {dl@#Tu
014: count++; EA:_PBZ
015: } s0Y7`uD^
016: } !vr
A\d
017: W70BRXe04D
018: return count; %&O'>L
019: } _=5\ $6
020: } ,E(M<n|.
021: } wGz_IL.D
注意,这个例子中的namespace应与第一个的一致,因为它们是同一个库中的.NumberOfDigits方法计算了参数中的数字的个数. w@N)Pu
第三个文件是FunctionClient.cs F0'o!A#|(
我们知道,一个库一旦建立,就可以被别的类利用(废话,要不然怎么叫库呢?).下面的C#程序就利用了我们刚才建立的库中的类. 6>d3*
000: // Libraries\FunctionClient.cs [di&N!Ao
001: using System; ]w8h#p
002: using Functions; S@L%X<Vm
003: class FunctionClient IgF#f%|Q
004: { >vfLlYx
005: public static void Main(string[] args) G)5Uiu:^X
006: { /X\:3P
007: Console.WriteLine("Function Client"); e+MsFXnB8
008: .fzns20u
009: if ( args.Length == 0 ) +zFEx%3^
010: { RoD9
011: Console.WriteLine("Usage: FunctionTest ... "); z\IZ5'
012: return; ,+_gx.H2j
013: } >&qaT*_g
014: /P{'nI
015: for ( int i = 0; i < args.Length; i++ ) ^6,}*@
016: { mc6W"
017: int num = Int32.Parse(args); s[*I210
018: Console.WriteLine( F.R0c@&W
019: "The Digit Count for String [{0}] is [{1}]", aOW~! f/M
020: args, \?k"AtL
021: DigitCount.NumberOfDigits(args)); du=[ r
022: Console.WriteLine( (5^SL Y
023: "The Factorial for [{0}] is [{1}]", VS<w:{*
024: num, QRY7ck:N
025: Factorial.Calc(num) ); `MMZR=LA
026: } ;xE1#ZT
027: } TP/bPZY
028: } ukXKUYNm8
在002行中,一个using Functions指明了引用Functions.DLL这个类. "k7C
如果我们在命令行中键入如下命令,就可以看到输出: )%?SWuS?N
FunctionTest 3 5 10 u z>V
输出: 1w?DSHe
Function Client Z5>}
The Digit Count for String [3] is [1] !:dhK
The Factorial for [3] is [6] zU>bT20x/
The Digit Count for String [5] is [1]
2Y9@[
The Factorial for [5] is [120] =$%_asQJ
The Digit Count for String [10] is [2] \o!B:Vb<
The Factorial for [10] is [3628800] cp 7;~i3
注意:当你运行这个.EXE文件时,它引用的DLL文件可以是在当前目录,子目录,或是CORPATH这个环境变量.CORPATH这个环境变量是在.NET环境中的类路径,用来指引系统寻找类.说白了,就是JAVA中的CLASSPATH,明白了吧,呵呵. /%)x!dmy
好了,又完了一篇,今天的任务完成了,可以休息了.唉,有什么好玩的呢? v.]W{~PI2V
C#中的版本处理 htqC~B{1E
现在我要说的是C#中的版本处理.其实这是任何一个软件必须要考虑的问题.每个软件都不只一个版本(除了我写的以外),因此版本处理显得非常地重要.JAVA很好地处理了这个问题,而我个人认为C#借鉴了JAVA的处理方法,所以,也做得很好. `>$l2,
在C#中,如果你在声明一个方法的时候用了virtual这个关键字,那么,在派生类中,你就可以使用override或者new关键字来弃用它或是忽略它.如果你在父类中用了virtual这个关键字,而在其派生类中又没有用override或new关键字,而直接引用一个同名方法的话,编译器将会报错,并将以new方式,即忽略派生类中的方法的方式来运行.下面的例子可以帮助你来理解: oo,3mat2C
000: // Versioning\versioning.cs fL R.2vJ
001: public class MyBase U[l{cRT
002: { 7vsXfIP+
003: public virtual string Meth1() E@ !~q
004: { a`QKNrA2
005: return "MyBase-Meth1"; m[*y9A1
006: } UXV>#U?
007: public virtual string Meth2() g(zoN0~
008: { WO6; K]
009: return "MyBase-Meth2"; T_?,?
010: } ;!N_8{
7r
011: public virtual string Meth3() q"^T}d d,
012: { V}"w8i+D?
013: return "MyBase-Meth3"; *}`D2_uP
014: } TYr"yZ([
015: } *Ry
"`"
016: 5},kXXN{+
017: class MyDerived : MyBase $P~Tt 4068
018: { 3MFb\s&Fq
019: public override string Meth1() IDv|i.q3
020: { r*s)T`T}}
021: return "MyDerived-Meth1"; |h1Y3
022: } lw 9rf4RF
023: public new string Meth2() cY\"{o"C
024: { i/WiSwh:
025: return "MyDerived-Meth2"; 8Ow0A
026: } XB-l[4?
027: public string Meth3() // 系统在这里将会有一个警告,并且将会隐藏方法Meth3() be{t yV
028: < {dV=
029: naKB2y]l
030: { 0(dXU\Y
031: return "MyDerived-Meth3"; 5 l(Q#pSX
032: } n*fsdo~
033: 5;-?qcb^w
034: public static void Main() f)K1j{TZ
035: { q'awV5y
036: MyDerived mD = new MyDerived(); E#cZM>
037: MyBase mB = (MyBase) mD; #AUz.WHD
038: .EQ1r7
9,
039: System.Console.WriteLine(mB.Meth1()); B&