程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> LINQ To SQL深入學習系列之二 C#3.0為LINQ的加強之二

LINQ To SQL深入學習系列之二 C#3.0為LINQ的加強之二

編輯:關於.NET

本文大部分內容整理自msdn

3、分部方法

分部方法使類的某個部分的實施者能夠定義方法(類似於事件)。類的另一部分的實施者可以決定是 否實現該方法。如果未實現該方法,編譯器將移除方法簽名以及對該方法的所有調用。因此,分部類中的 任何代碼都可以隨意地使用分部方法,即使未提供實現也是如此。如果調用了未實現的方法,將不會導致 編譯時錯誤或運行時錯誤。

在自定義生成的代碼時,分部方法特別有用。這些方法允許保留方法名稱和簽名,因此生成的代碼可 以調用方法,而開發人員可以決定是否實現方法。與分部類非常類似,分部方法使代碼生成器創建的代碼 和開發人員創建的代碼能夠協同工作,而不會產生運行時開銷。

分部方法聲明由兩個部分組成:定義和實現。它們可以位於分部類的不同部分中,也可以位於同一部 分中。

namespace PM
{
partial class A
{
partial void OnSomethingHappened(string s);
}
// This part can be in a separate file.
partial class A
{
// Comment out this method and the program
// will still compile.
partial void OnSomethingHappened(String s)
{
Console.WriteLine("Something happened: {0}", s);
}
}
}

要點:

1、分部方法聲明必須以上下文關鍵字 partial 開頭,並且方法必須返回 void。

2、分部方法可以有 ref 參數,但不能有 out 參數。

3、分部方法為隱式 private 方法,因此不能為 virtual 方法。

4、分部方法不能為 extern 方法,因為主體的存在確定了方法是在定義還是在實現。

5、分部方法可以有 static 和 unsafe 修飾符。

6、分部方法可以為泛型的。約束將放在定義分部方法聲明上,但也可以選擇重復放在實現聲明上。參 數和類型參數名稱在實現聲明和定義聲明中不必相同。

7、不能將委托轉換為分部方法。

場景舉例:輕量級事件處理

有的時候,自動生成的代碼需要事件這類語言構造來通知用戶對某些操作進行處理,但實際上用於編 寫的代碼就位於自動生成的類型之中。此時,或者需要觸發一個事件,或者就需要生成一個virtual方法 來讓用戶繼承。但無論是事件還是繼承,開銷都是比較大的,所以可以通過分部方法來實現輕量級的處理 方式。如下面的類:

partial class Customer
{
string name;
public string Name
{
get
{
return name;
}
set
{
OnBeforeUpdateName();
OnUpdateName();
name = value;
OnAfterUpdateName();
}
}
partial void OnBeforeUpdateName();
partial void OnAfterUpdateName();
partial void OnUpdateName();
}

這裡定義了三個分部方法,其意義不言而喻。假設這是系統自動生成的代碼,則我們只需在另外一個 源代碼文件中的partial class Customer中實現這幾個分部方法即可。

另外在自定義DataContext中的Insert、Update、Delete方法也會用到分部類,等我們講到 DataContext時再詳細講解這部分。

4、擴展方法:

擴展方法使您能夠向現有類型“添加”方法,而無需創建新的派生類型、重新編譯或以其他方式修改 原始類型。擴展方法是一種特殊的靜態方法,調用擴展方法與調用在類型中實際定義的方法之間沒有明顯 的差異。擴展方法是可以通過使用實例方法語法調用的靜態方法。效果上,使得附加的方法擴展已存在類 型和構造類型成為可能。他可以對現有類功能進行擴充,從而使該類型的實例具有更多的方法。擴展方法 有助於把今天動態語言中流行的對快速錄入支持的靈活性,與強類型語言之性能和編譯時驗證融合起來。 這裡先舉一個msdn中的例子:

下面的示例演示為 System.String 類定義的一個擴展方法。假設我要分析一個字符串,希望得到字符 串中單詞的個數,一般情況下我們可能使用一個統計的函數來解決這個問題

static void Main(string[] args)
{
string s = "Hello Extension Methods";
Console.WriteLine(WordCount(s));
}
static int WordCount(string str)
{
return str.Split(new char[] { ' ', '.', '?' }, StringSplitOptions.RemoveEmptyEntries).Length;
}

但這樣用起來感覺上可能會很別扭,這個WordCount方法如果就是字符串類中的一個方法多好,像所有字 符串的實例方法一樣用。這裡我們引出擴展方法來解決這個問題。

namespace ExtensionMethods
{
public static class MyExtensions
{
public static int WordCount(this String str)
{
return str.Split(new char[] { ' ', '.', '?' }, StringSplitOptions.RemoveEmptyEntries).Length;
}
}
}

注意,上面的靜態方法在第一個類型是string的參數變量前有個“this”關鍵詞,這告訴編譯器,這 個特定的擴展方法應該添加到類型為“string”的對象中去。

使用 using 指令將 WordCount 擴展方法放入范圍中:

using ExtensionMethods;

string s="HelloExtensionMethods";
int i=s.WordCount();

擴展方法要點

1、擴展方法的本質為將實例方法調用在編譯期改變為靜態類中的靜態方法調用。事實上,它確實擁有 靜態方法所具有的所有功能。

2、通常,您更多時候是調用擴展方法而不是實現您自己的擴展方法。由於擴展方法是使用實例方法語 法調用的,因此不需要任何特殊知識即可從客戶端代碼中使用它們。若要為特定類型啟用擴展方法,只需 為在其中定義這些方法的命名空間添加 using 指令。

3、擴展方法的優先級:現有實例方法優先級最高,其次為最近的namespace下的靜態類的靜態方法, 最後為較遠的namespace下的靜態類的靜態方法。(與接口或類方法具有相同名稱和簽名的擴展方法永遠 不會被調用 )

4、在代碼中,可以使用實例方法語法調用該擴展方法。但是,編譯器生成的中間語言 (IL) 會將代碼 轉換為對靜態方法的調用。因此,並未真正違反封裝原則。實際上,擴展方法無法訪問它們所擴展的類型 中的私有變量。

擴展方法通用准則

1、通常,建議您只在不得已的情況下才實現擴展方法,並謹慎地實現。只要有可能,必須擴展現有類 型的客戶端代碼都應該通過創建從現有類型派生的新類型來達到這一目的。

2、在使用擴展方法來擴展您無法更改其源代碼的類型時,您需要承受該類型實現中的更改會導致擴展 方法失效的風險。

3、如果您確實為給定類型實現了擴展方法,請記住以下兩點:

如果擴展方法與該類型中定義的方法具有相同的簽名,則擴展方法永遠不會被調用。

擴展方法被在命名空間級別放入范圍中。例如,如果您在同一個名為 Extensions 的命名空間中具有 多個包含擴展方法的靜態類,則這些擴展方法將全部由 using Extensions; 指令放入范圍中。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved