partial class 說明


C# 2.0 可以將類、結構或接口的定義拆分到兩個或多個源文件中,在類聲明前添加partial關鍵字即可。

例如:下面的PartialTest類

class PartialTest

{

string Str_FieldTest;

int Int_FieldTest;

public void DoTest()

{

Debug.Print("Test");

}

}

可在不同源文件中寫成下面形式:

一個文件中寫:

partial class PartialTest

{

string Str_FieldTest;

int Int_FieldTest;

}

另一個文件中寫:

partial class PartialTest

{

public void DoTest()

{

Debug.Print("Test");

}

}

 

什么情況下使用分部類?

–處理大型項目時,使一個類分布於多個獨立文件中可以讓多位程序員同時對該類進行處理(相當於支持並行處理,很實用);

–使用自動生成的源時,無需重新創建源文件便可將代碼添加到類中。Visual Studio 在創建Windows 窗體、Web 窗體時都使用此方法。你不用編輯Visual Studio 所創建的文件,便可創建使用這些類的代碼。換句話說:系統會自動創建一個文件(一般記錄的是窗體及窗體中的控件的屬性),另一個或幾個文件記錄的是用戶自己編寫的代碼。這兩部分分開可以使結構顯得非常清晰,用戶只需關注自己負責的那部分就行了(需要的話,這兩部分可以互相調用)。等到了編輯運行的時候,系統會自動將這兩部分合成一個文件。

 

使用Partial需要注意以下一些情況:

1.使用partial 關鍵字表明可在命名空間內定義該類、結構或接口的其他部分

2.所有部分都必須使用partial 關鍵字

3.各個部分必須具有相同的可訪問性,如public、private 等

4.如果將任意部分聲明為抽象的,則整個類型都被視為抽象的

5.如果將任意部分聲明為密封的,則整個類型都被視為密封的

6.如果任意部分聲明繼承基類時,則整個類型都將繼承該類

7.各個部分可以指定不同的基接口,最終類型將實現所有分部聲明所列出的全部接口

8.在某一分部定義中聲明的任何類、結構或接口成員可供所有其他部分使用

9.嵌套類型可以是分部的,即使它們所嵌套於的類型本身並不是分部的也如此。如下所示:

class Container

{

partial class Nested

{

void Test1();

}

partial class Nested

{

void Test2();

}

}

 

使用分布類的一些限制:

 

1.要作為同一類型的各個部分的所有分部類型定義都必須使用partial 進行修飾。如下所示:

public partial class A { }

public class A { } // Error, must also be marked partial

2. partial 修飾符只能出現在緊靠關鍵字class、struct 或interface前面的位置(枚舉或其它類型都不能使用partial);

3. 要成為同一類型的各個部分的所有分部類型定義都必須在同一程序集和同一模塊(.exe 或.dll 文件)中進行定義。分部定義不能跨越多個模塊;

4. 類名和泛型類型參數在所有的分部類型定義中都必須匹配。泛型類型可以是分部的。每個分部聲明都必須以相同的順序使用相同的參數名。
------------------------------------------------------------------------------------------------------------------------------------------

partial class擴展功能新思路

開閉原則:“對修改封閉,對擴展開放”。在面向對象的系統中,通過類的繼承實現擴展。.net中提供的partial class提供了擴展類的新思路。

一、應用場景

可以使用partial class的場景很多。這里分析一個ORM的例子。
系統中有一個Cat類,屬性ID、Age、Weight都需要存儲到數據庫中,一個信息系統中常見的需求。通過讀取數據庫的結構,可以用工具生成Cat類的代碼。並且ORM框架支持了從數據庫信息生成Cat對象。
現在的Cat什么動作都沒有,客戶說,我們需要一個Miaow()的函數。這時就需要對ORM生成的Cat類進行擴展了。
可以肯定地一點是,我們不能修改自動生成的代碼,因為這會牽涉到數據庫結構與代碼同步的問題。解決這個需求有兩種方法:繼承方式擴展,partial class擴展。

 

 

二、繼承方式擴展

工具自動生成一個CatBase類,這個類只有屬性,嵌入到ORM框架中。既然需要擴展功能,很容易想到對這個基類繼承,於是有了Cat類。Cat類如願以償地有了Miaow()函數。
以前系統中用的是CatBase的實例,現在創建CatBase實例的地方需要改為創建Cat的實例。這個問題讓ORM框架解決吧。
客戶的需求實現了,我們自己的代碼生成也沒有遭到破壞,任務完成。

三、partial class擴展

partial class簡單地說就是可以將一個類的代碼寫到兩個或多個代碼文件中。編譯器在編譯的過程中將這幾個文件組合起來一起編譯。一個很酷的技術。
工具生成的Cat類仍然不變。既然需要增加函數,那么在新建一個代碼文件,將Miaow()函數寫出來就可以。需要做的僅僅是將類的聲明由class改為partial class,任務完成。

四、對比分析

兩種思路都可以實現需求。孰優孰劣需要仔細分析一下。
實例創建:partial class更加簡潔。
系統復雜度:對於系統來說,partial class方式下只存在一個類,而繼承方式有兩個類。
繼承邏輯:從邏輯上講,Cat並不需要一個基類CatBase,這樣做僅僅是因為在代碼構建過程中的一個限制。
維護性:兩種方式下都會存在兩個代碼文件,維護成本並沒有區別。
可讀性:兩個Cat文件確實讓人費解。

整體上說,使用partial class更加優雅一些。
“繼承”的這種方式比較符合傳統的思維習慣,而partial class到底是不是滿足開閉原則呢,這點確實不好說。不過在軟件構建上,我是一個實用主義者,哪種方式好用就用哪一種。
在ORM的場景中,partial class更加好一些,但有的時候,兩個類之間確實就存在繼承關系,那么就必須用到繼承了。雖然絕大多數情況下,都需要繼承方式,但是既然有了partial class技術,我們在做設計時也需要考慮這個思路。

在VS2005中,Form、DataSet都使用了partial class方式,原理和這個一樣。但是要將這個原理推廣到“業務實體”中,可能在理解上需要有所突破。

使用partial class確實會帶來可讀性的損失,尤其是一個類分布在很多個文件中的時候,所以文件的命名最好是有一個規范來保證。

轉自:http://www.cnblogs.com/dafozhang/archive/2011/12/23/2299023.html

 

partial關鍵字的含義和使用

partial關鍵字 C#2.0提供的新關鍵字,用來將一個class、struct或interface的定義拆分,寫在不同的源文件中。每個源文件包含類定義的一部分,編譯應用程序時將把所有部分組合起來。在以下幾種情況下需要拆分類定義:

    1.處理大型項目時,使一個類分布於多個獨立文件中可以讓多位程序員同時對該類進行處理。

    2.使用自動生成的源時,無需重新創建源文件便可將代碼添加到類中。Visual Studio 在創建 Windows 窗體、Web 服務包裝代碼等時都使用此方法。無需編輯 Visual Studio 所創建的文件,便可創建使用這些類的代碼。

    用法如下: [modifiers] partial type

    modifier包括abstract new override virtual static extern和四個訪問修飾符(public private protected internal)其中的一個。Type包括 class struct interface其中的一個。

 
    看下面的定義:
 
public partial class Employee
...{
    public void DoWork()
    ...{}
}
public partial class Employee
...{
    public void GoToLunch()
    ...{}
}
 
     以上代碼定義了一個類Employee,該類有兩個方法DoWork()和GoToLunch(),你完全可以把以上代碼看作是:    而實際上編譯器在編譯時也是這么合並的。編譯器在編譯時會把一個partial類所有的信息放到一起,我們可以再來擴充一下。 假如我們已經定義好了兩個接口: 我們的類定義如下:    這在開發分布式系統時是很有必要的,多個程序員只要分別開發自己的一部分就可以了。
 
public class Employee
...{
    public void DoWork()
...{}
    public void GoToLunch()
...{}
}

 

interface IDoSomeThing
...{
    void DoWork();
    void DoPlay();
}

interface IGoToDinner
...{
    void GoToBreakfast();
    void GoToLunch();
    void GoToSupper();
}

 

public partial class Employee : IDoSomeThing
...{
    public void DoWork()
    ...{}

    public void DoPlay()
    ...{}
}

public partial class Employee : IGoToDinner
...{
    public void GoToBreakfast()
    ...{}

    
    [System.ObsoleteAttribute]
    public void GoToLunch()
    ...{}

    public void GoToSupper()
    ...{}
}

於是,在編譯時編譯器就把以上合並為一個類:

public class Employee : IDoSomeThing, IGoToDinner
...{
    public void DoWork()
    ...{}

    public void DoPlay()
    ...{}

    public void GoToBreakfast()
    ...{}

    
    [System.ObsoleteAttribute]
    public void GoToLunch()
    ...{}

    public void GoToSupper()
    ...{}
}

 

其中有幾點需要注意:
1.    要作為同一類型的各個部分的所有分部類型定義都必須使用 partial 進行修飾。下面這樣就錯誤
public partial class A { }
//public class A { } // Error, must also be marked partial
2.partial 修飾符只能出現在緊靠關鍵字 class、struct 或 interface 前面的位置。
3.   分部類型定義中允許使用嵌套的分部類型。當然,如果嵌套類也是partial類的話,同樣遵守上面的規則。例如:
partial class ClassWithNestedClass
...{
    partial class NestedClass ...{ }
}

partial class ClassWithNestedClass
...{
    partial class NestedClass ...{ }
}
 
4. 要成為同一類型的各個部分的所有分部類型定義都必須在同一程序集和同一模塊(.exe 或 .dll 文件)中進行定義。分部定義不能跨越多個模塊。
5. 類名和泛型類型參數在所有的分部類型定義中都必須匹配。泛型類型可以是分部的。每個分部聲明都必須以相同的順序使用相同的參數名。
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM