从零开始学习C# 2
繼續《C#入門經典》,Let's go!
方法的重載
重載也是多態的一種體現,其表現形式是方法名相同,但簽名不同。所謂簽名就是方法名以及參數,換句話說,重載方法就是幾個參數不同的同名方法,在調用的時候,編譯器根據輸入的參數類型選擇對應的重載方法。注意的是,返回值不是方法簽名的一部分,因此不能定義只有返回值不同的方法。
OverloadSample 1 int Max(int a, int b)2 {
3 return a > b ? a : b;
4 }
5
6 double Max(double a, double b)
7 {
8 return a > b ? a : b;
9 }
10
11 double Max(ref double a, double b)
12 {
13 return a > b ? a : b;
14 }
15
16 //不能定義僅在out和ref上有差別的方法
17 //double Max(out double a, double b)
18 //{
19 //}
委托
C++程序猿可能比較熟悉所謂的“函數指針”,委托就類似于函數指針。我的理解是提供了一種像操作變量一樣的操作方法的方式,這么說可能比較抽象,讓我們看個例子先:
DelegateSample 1 class DelegateClass2 {
3 public delegate int ProcessDelegate(int a, int b);
4 }
5
6 class MethodClass
7 {
8 public int Add(int a, int b)
9 {
10 return a + b;
11 }
12
13 public static int Mutiply(int a, int b)
14 {
15 return a * b;
16 }
17 }
18
19 class Program
20 {
21 static void Main(string[] args)
22 {
23 MethodClass method = new MethodClass();
24 DelegateClass.ProcessDelegate addDelegate = new DelegateClass.ProcessDelegate(method.Add);
25 DelegateClass.ProcessDelegate mutiplyDelegate = new DelegateClass.ProcessDelegate(MethodClass.Mutiply);
26
27 Console.WriteLine(addDelegate(10, 10));
28 Console.WriteLine(mutiplyDelegate(10, 10));
29 Console.ReadLine();
30 }
31 }
先看DelegateClass,該類中定義了一個委托,委托定義的語法類似于抽象方法,利用delegate關鍵字,委托沒有方法體。然后我們在MethodClass中定義了兩個方法,注意,想方法簽名必須和委托定義一致,這樣才能使用委托來調用該方法。接著,我們在Main方法中實例化了兩個委托,并將MethodClass中的兩個方法作為參數分別傳入。注意這里的語法,method.Add,MethodClass.Mutiply是不是很類似于屬性呢?對委托的實例化是不是也和實例化一個類很類似呢?這就是我之前說的“提供了一種像操作變量一樣的操作方法的方式”。實例化之后addDelegate就代表了Add方法,mutiplyDelegate就代表了Mutiply方法,然后就可以像使用普通方法一樣來使用委托了。
委托至少在一個地方是非常有用的,當調用者所調用的方法在他編寫代碼的時候并不能確定的,就需要使用委托,這就是所謂回調,是事件處理的基礎。比如由A提供一個委托,B實現一個方法,并傳遞給A所定義的委托,這樣A就可以調用B所實現的方法了。想想點擊一個Button的事件處理的方法是誰寫的,又是誰在調用你就會明白。我在之后的文章中還會討論事件處理,到時候會對此再進行研究。
書的第七章分兩部分,第一部分主要講了一些調試的技巧包括斷點,條件斷點,監視,即時窗口等,十分有用。在這里我就不贅述了,大家最好看圖動手,自己嘗試一下~第二部分是異常處理,這是一個重要的議題,但感覺和Java十分類似,沒什么需要注意的。如果第一次接觸的話建議好好看一下,注意異常處理并不是錯誤處理,而應該把他理解成處理非正常流程的一種很好的方法(一個舉爛了的例子,比如在ATM取款的時候發現沒錢了,這不是一個正常的流程,但也是十分可能出現的情況,并不是ATM出現錯誤(故障),只是一種異常的流程而已)。正確的使用異常處理可以極大得增強代碼的健壯性。
屬性
屬性在我看來就是簡化了代碼,Java中需要給私有變量提供set和get方法,用來安全地訪問變量,而在C#中,是利用了屬性,看上去不是方法,變得簡單了,實際上編譯完的MSIL依然是這兩個方法,只是我們看不到罷了。
接口
OOP中很重要的概念,不熟悉OOP的好好看看吧。這里主要提一下文中的一個觀點,個人感覺比較有用:接口在發布后最好不要修改它,如果修改了接口就會導致之前實現接口的代碼不能正常工作。我們應該創建一個新的接口來擴展舊接口,例如包換一個版本號,如X2,這是創建接口的標準方式。
IDisposable接口,提供了Dispose方法。使用這個接口的目的是就是讓用戶自己釋放重要的稀有資源,由于GC的運行時間是不固定的,稀有資源(例如IO,數據庫連接等)如果不能及時釋放將會導致程序性能下降。在使用完資源之后調用Dispose方法就可以釋放資源。
DisposeSample 1 //Form類實現了IDisposable接口2 Form form1 = new Form();
3 //進行一些操作, 然后Dispose釋放資源
4 form1.Dispose();
5
6 //另一種使用IDisposable的方式
7 //注意括號里必須是實現IDisposable的類
8 using(Form form1 = new Form())
9 {
10 //進行一些操作, 之后C#會自己調用Dispose方法釋放資源
11 }
Dispose方法有一種通用的實現方式:
DisposeImplementionSample 1 public void Dispose()2 {
3 Dispose(true);
4 //GC調用對象的Finalize方法會損失性能, 因此自己釋放了資源就不用GC再次釋放了, 執行下面的語句就是為了這個目的
5 GC.SuppressFinalize(this);
6 }
7 // Dispose(bool disposing) 執行分兩種不同的情況.
8 // 如果disposing 等于 true, 手動釋放
9 // 如果disposing 等于false, 方法已經被終結器 finalizer 從內部調用過
10 protected virtual void Dispose(bool disposing)
11 {
12 if(disposing)
13 {
14 //執行手動釋放
15 }
16 }
關于Dispose,GC等內容還很多,聽說CLR via C#里面講得十分詳細,等看過之后再與大家分享。
繼承
沒什么好說的,OOP的基本概念,需要注意的是C#提供了virtual,override和new關鍵字來處理繼承成員(不只是方法,屬性字段也可以),他們之間的關系需要搞清楚。只有virtual成員才能被override,如果virtual成員在派生類中有對應的override成員,那么編譯器會自動使用派生類的成員,稱為多態,否則始終使用基類成員:
InheritSample 1 interface IPerson2 {
3 void Hello();
4 void Bye();
5 }
6 class Person : IPerson
7 {
8 public void Hello()
9 {
10 Console.WriteLine("Hello, person");
11 }
12
13 public virtual void Bye()
14 {
15 Console.WriteLine("Bye, person");
16 }
17
18 //如果沒有下面兩個方法,那么上面兩個方法會被編譯器當做對接口的實現,稱為隱式實現,下面的稱為顯示實現
19 void IPerson.Hello()
20 {
21 Console.WriteLine("Hello, iperson");
22 }
23
24 void IPerson.Bye()
25 {
26 Console.WriteLine("Bye, iperson");
27 }
28 }
29
30 class A : Person
31 {
32 //隱藏了基類Person的Hello,VS會提示使用new來顯示隱藏
33 public void Hello()
34 {
35 Console.WriteLine("Hello, a");
36 }
37
38 //隱藏了基類Person的Bye,VS會提示使用new來顯示隱藏
39 public void Bye()
40 {
41 Console.WriteLine("Bye, a");
42 }
43 }
44
45 class B : Person
46 {
47 public new void Hello()
48 {
49 Console.WriteLine("Hello, b");
50 }
51
52 public override void Bye()
53 {
54 Console.WriteLine("Bye, b");
55 }
56 }
57
58 class Program
59 {
60 static void Main(string[] args)
61 {
62 IPerson[] people = new IPerson[3];
63 people[0] = new Person();
64 people[1] = new A();
65 people[2] = new B();
66 foreach (IPerson person in people)
67 {
68 person.Hello();
69 person.Bye();
70 }
71 foreach (Person person in people)
72 {
73 person.Hello();
74 person.Bye();
75 }
76 Console.ReadLine();
77 }
78 }
一些補充
補充一下,之前一篇文章提到的partial類,其實還有partial方法,partial方法必須是private,且不能是virtual,override,abstract,new,sealed和extern,最后,partial方法的參數不能是out,但可以是ref。partial方法在一個partial類中定義,但不實現,在另一個partial類中實現,如:
PartialMethod 1 partial class MyClass2 {
3 partial void DoSthElse();
4
5 void DoSth()
6 {
7 Console.WriteLine("Do sth start.");
8 DoSthElse();
9 Console.WriteLine("Do sth end");
10 }
11 }
12
13 partial class MyClass
14 {
15 partial void DoSthElse()
16 {
17 Console.WriteLine("Do sth else.");
18 }
19 }
如果刪除掉partial方法的實現或者該partial類,那么那句DoSthElse的調用就不會被編譯,這就是partial方法用處。在自動生成的代碼中,自動生成一個partial方法由用戶來實現,這樣可以略微提供性能。說道這里,再思考一下為什么partial方法為什么不能有返回值呢?大家可以想一想(提示:如果有的話,在使用返回值的時候會發現什么?)
VS的類圖編輯器還不錯,輕量級,而且也有反向工程,使用比較簡單,圖形看上去也比Rose,PowerDesigner之流漂亮,而且在VS里集成,用不著再開一個進程啦~
嗯,差不多就這樣了,希望大家多提意見,有問題也可以一起討論,多多交流。
轉載于:https://www.cnblogs.com/applepie/archive/2011/10/01/cshape_study_2.html
總結
以上是生活随笔為你收集整理的从零开始学习C# 2的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows下的.NET+ Memca
- 下一篇: POJ 3648 Wedding