用c#編寫程式也有段時間了,但有很多概念其實也搞得不是很清楚,或者只是簡單的拷貝一下已有的代碼,修修改改也能弄出一個東西,但真正要空手寫一個還是有點難度。這幾天打算重新好好學習一下最基本的東西。手頭有一本Microsoft .NET架構程式設計(修訂版)(Jeffrey Richter),要好好重溫一下。
1.類型的存取控制(控制由松到嚴格)
public:可以被任何程式集中的任何代碼調用。
internal(assembly,VB中是Friend):可以被同一程式集中的任何代碼調用。
protected(Family):可以被同一類型中和衍生類別型中的代碼調用,不能被其他類訪問。
private:只能在同一個類型中訪問。
預設為internal。
2.new一個對象所進行的操作
a.從託管堆中分配指定類型所需數量位元組來作為儲存其對象的記憶體空間
b.初始對象的附加成員。每一個對象都有兩個附加成員,CLR使用這兩個成員來管理對象。一個為指向類方法表的指標,另一個為SyncBlockIndex。
c.傳入new操作符指定的參數,調用建構函式。
3.is操作符和typeof
用來判斷某個對象是否某個類型(或基類)。返回true或者false。如果對象為null,則肯定返回false。
bool b =o is object;
而typeof()輸入一個類型(而非執行個體),返回一個system.type的執行個體。
4.基元類型和FCL類型
基元類型和FCL類型有對應關係。c#語言規範中推薦使用基元類型。但Jeffrey Richter推薦使用FCL類型。
常用的一些對應有
基元類型 FCL類型 備忘
byte System.Byte
int System.Int32
long System.Int64
float System.Single
double System.Double
bool System.Boolean
5.裝箱和拆箱
裝箱就是將實值型別轉化為應用類型
拆箱則相反
裝箱的過程:
a.在託管堆中新產生一個空間,並將實值型別的執行個體所有成員拷貝到這個新的空間
b.返回新開空間的引用
6.類(型)的成員
a.常數:常數是靜態,是屬於類的而不是屬於執行個體的,不能用this訪問
public const int theConst=0;
b.readonly修飾:readonly修飾的變數是屬於執行個體的,能夠在建構函式中修改其值
c.類型構造器(靜態建構函式):初始化類型的靜態欄位。
static classname(){},不能用public等修飾,不能帶參數。在類型第一次被訪問的時候執行。
d.靜態成員(static):屬於類型,不屬於執行個體,在靜態方法中不能訪問非靜態成員。在非靜態成員中能夠訪問靜態成員,但不能加this
7.類型的預定義特性(abstract,sealed)
abstract(VB:MustInherit):不能被執行個體化,可以做基類。基類可以被執行個體化
sealed(VB:NotInheritable):不能作為基類
8.欄位和方法的預定義特性
a.欄位預定義特性
static(VB:Shared)
readonly
b.方法預定義特性
static(VB:Shared):靜態方法,屬於類型而非類的執行個體
virtual(VB:overridable):當方法被調用的時候,按照對象繼承鏈最末端的方法調用。父類的virtual和子類的override配合,就能被繼承鏈的最末端調用,否則會按照編譯時間的類型調用。要被重寫的(override)方法,在基類應該寫virtual。
new(VB:Shadows):不重寫基類方法
override(Overrides):重寫基類方法,與基類的virtual配合
abstract(Mustoverride)
sealed(NotOverridable)
9.委託
委託相當於函數指標,用型別安全的方法來提供函數回調機制。
函數名是一個委託的執行個體。
a.定義委託類型
在類的內部或者類的外部,地位相當於一種類型。
public delegate void FeedBack(string arg1,string arg2);
其中,void表示該委託類型的傳回值,小括弧內表示該委託類型的參數
b.定義委託執行個體
FeedBack fb=new FeedBack(函數名);
或者先定義一個指向null的委託,再往這個委託的委託鏈上添加函數
FeedBack fb=null;
fb+=函數名;
或者乾脆直接用函數名稱作為一個委託的執行個體
FeedBack fb=函數名;
10.類的事件
a:定義一個事件參數類(和該類在同一個命名空間內),繼承自EventAgrs
b:定義一個委託類型(和該類在同一個命名空間內) public delegate void EventHandler(object sender,EventArgs e);
c:在類裡面定義事件(其實是定義一個委託)
public event EventHandler OnEvent;(event關鍵字可以省略)
d:引發事件
if(OnEvent!=null)
{
OnEvent(sender,e);
}
如果事件被註冊了就不會為null
捕獲事件
訂閱:對象名.OnEvent+=new EventHandler(處理函數名稱);
取消訂閱:對象名.OnEvent-=new EventHandler(處理函數名稱);
注意:只要一個對象仍然登記有另外一個對象的事件,該對象就不能被執行記憶體回收
所以應該在必要的地方登出所有的事件註冊
11.異常處理
異常處理一直是讓人感到迷茫的地方,哪裡應該捕獲異常,哪裡不應該捕獲異常,捕獲的異常應該如何處理,異常對程式效能的影響等等問題,是要搞清楚的問題。
異常是對程式界面隱含式假設的一種違反。那麼如何通知調用者違反了假設呢?答案就是拋出一個異常。
c#可以唯寫catch,不寫小括弧,表示捕捉所有的異常。可以thorw,不寫拋出什麼異常,代表拋出所捕獲的異常。
finally內部的代碼用於做一些清理工作(如關閉檔案,關閉資料庫連結等),即使try裡面的代碼拋出異常,或者try裡面有return,finally的代碼也會執行。可以認為向上拋出異常和return是同樣層級的,而finally則在它們之前進行運行
12.介面
13.遞迴的編寫
一個遞迴的類:
public class Node
{
public string Name;
public List<Node> Childs;
}
用一個函數列印這個類:
private void print(Node n)
{
Console.WriteLine(n.Name);
//每層遞迴的操作
if (n.Childs != null)
{
foreach (Node c in n.Childs)
{
print(c);
}
}
//跳出遞迴的條件
}
14.繼承
問題:當子類執行個體化的時候,和父類的建構函式有什麼關係?如何顯式調用父類的建構函式?
15:
c#的一個case中不能像vb那樣同時寫多個條件,但能夠這樣寫:
switch (afn)
{
case 0x00:
case 0x01:
case 0x02:
case 0x03:
case 0x04:
case 0x05:
case 0x06:
case 0x0A:
case 0x0B:
case 0x0C:
case 0x0D:
case 0x0E:
case 0x0F:
case 0x10:
return (AFNS)afn;
default:
return AFNS.Unknown;
}
(也就是說,如果case中沒有語句,就可以不使用break)
16.base 關鍵字
用於從衍生類別中訪問基類的成員:
a.調用基類上已被其他方法重寫的方法。
b.指定建立衍生類別執行個體時應調用的基類建構函式。
c.基類訪問只能在建構函式、執行個體方法或執行個體屬性訪問器中進行。從靜態方法中使用 base 關鍵字是錯誤的。
調用基類方法:
public class Person
{
protected string ssn = "444-55-6666";
protected string name = "John L. Malgraine";
public virtual void GetInfo()
{
Console.WriteLine("Name: {0}", name);
Console.WriteLine("SSN: {0}", ssn);
}
}
class Employee : Person
{
public string id = "ABC567EFG";
public override void GetInfo()
{
// Calling the base class GetInfo method:
base.GetInfo();
Console.WriteLine("Employee ID: {0}", id);
}
}
調用基類建構函式:
public class BaseClass
{
int num;
public BaseClass()
{
Console.WriteLine("in BaseClass()");
}
public BaseClass(int i)
{
num = i;
Console.WriteLine("in BaseClass(int i)");
}
public int GetNum()
{
return num;
}
}
public class DerivedClass : BaseClass
{
// This constructor will call BaseClass.BaseClass()
public DerivedClass() : base()
{
}
// This constructor will call BaseClass.BaseClass(int i)
public DerivedClass(int i) : base(i)
{
}
static void Main()
{
DerivedClass md = new DerivedClass();
DerivedClass md1 = new DerivedClass(1);
}
}
dispose與finalize
可參考blog:http://www.cnblogs.com/xlshcn/archive/2007/01/16/idisposable.html
// Design pattern for a base class.
public class Base: IDisposable
{
//Implement IDisposable.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// Free other state (managed objects).
}
// Free your own state (unmanaged objects).
// Set large fields to null.
}
// Use C# destructor syntax for finalization code.
~Base()
{
// Simply call Dispose(false).
Dispose (false);
}
}
// Design pattern for a derived class.
public class Derived: Base
{
protected override void Dispose(bool disposing)
{
if (disposing)
{
// Release managed resources.
}
// Release unmanaged resources.
// Set large fields to null.
// Call Dispose on your base class.
base.Dispose(disposing);
}
// The derived class does not have a Finalize method
// or a Dispose method without parameters because it inherits
// them from the base class.
}
x.gettype和typeof的用法
1.判斷某個執行個體是否某個類型
c# o is classname
vb typeof o is classname
2.c# typeof(int)
bv gettype(integer)
3.object類的方法
c# o.GetType
vb o.GetType
x.關於類的繼承,重寫等 (override)