C# 3.0 feature 2--Extension methods
Extension method,可以對現有類功能進行擴充,從而使該型別的例項具有更多的方法(功能)。
有人可能會提出疑問,如果是對類進行擴充,那使用繼承不就ok了?是的,使用繼承確實可以達到擴充功能的目的,但也會帶來更多的問題,比如該使用子類的地方,傳入的卻是父類物件;比如想擴充的類為第三方提供,我們無法得知其內部細節等等。拋開這些統統不談,為了讓一個型別的例項增加一個方法,我們就要使用繼承創造自己的子類?這顯然不是一個好辦法,相對於這些, Extension method給我們提供了一個簡便,靈活的解決方案。
我們先來看一個例子。
上面的例子中,我們對int的方法進行了擴充,為其增加了Square方法。
下面是編繹後的IL程式碼。
我們發現原來extension method也沒什麼玄乎的,編繹器會將其編繹為對Square(i)的呼叫,原來就是靜態類中方法呼叫。
將Extension Method改為靜態方法,並在Main函式中直接呼叫
可以看到,兩種程式碼產生的IL程式碼一模一樣。
下面說下如何定義Extension Method,首先,Extension Method必須定義在普通的 static class內,這裡講的普通是static class不能為泛型(non-generic)或者內嵌(non-nested)的。其次,Extension Method的第一個引數必須為this + 型別 + 變數名。該引數指定了擁有該方法的型別為 this指定的型別。可能有的人會問,即然this指定的型別擁有,那麼可不可以使用型別的私有或受保護的成員?很遺憾,不能。記住,Extension Method僅僅是看起來像是一個型別的方法,但其實質上不是,它更像是靜態型別的靜態方法,事實上,它確實擁有靜態方法所具有的所有功能。
說完了這些,再說一下Extension Method的作用域,它是整個namespace可見的,並且可以通過using namespace來匯入其它名稱空間中的Extension Method. 匯入的擴導方法有沒有可能因為跟原型別的重名方法衝突而導致編繹失敗呢?不會。如果有同名的方法,Extension Method會出現在該方法Intellisense中的Parameter Help和Quick Info中,我們可以象呼叫過載函式一樣呼叫它。
最後再說一下Extension Method的結合順序,它是自左向右結合的,比如x有兩個Extension Method方法A,B,x.A().B()將被編繹為B(A(x)).
有人可能會提出疑問,如果是對類進行擴充,那使用繼承不就ok了?是的,使用繼承確實可以達到擴充功能的目的,但也會帶來更多的問題,比如該使用子類的地方,傳入的卻是父類物件;比如想擴充的類為第三方提供,我們無法得知其內部細節等等。拋開這些統統不談,為了讓一個型別的例項增加一個方法,我們就要使用繼承創造自己的子類?這顯然不是一個好辦法,相對於這些, Extension method給我們提供了一個簡便,靈活的解決方案。
我們先來看一個例子。
namespace CSharp
{
class Program
{
static void Main(string[] args)
{
int i = 6;
Console.WriteLine(i.Square());
}
}
static class Extensions
{
public static int Square(this int i)
{
return i * i;
}
}
}
{
class Program
{
static void Main(string[] args)
{
int i = 6;
Console.WriteLine(i.Square());
}
}
static class Extensions
{
public static int Square(this int i)
{
return i * i;
}
}
}
上面的例子中,我們對int的方法進行了擴充,為其增加了Square方法。
下面是編繹後的IL程式碼。
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 16 (0x10)
.maxstack 1
.locals init ([0] int32 i)
IL_0000: nop
IL_0001: ldc.i4.6
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: call int32 CSharp.Extensions::Square(int32)
IL_0009: call void [mscorlib]System.Console::WriteLine(int32)
IL_000e: nop
IL_000f: ret
} // end of method Program::Main
{
.entrypoint
// Code size 16 (0x10)
.maxstack 1
.locals init ([0] int32 i)
IL_0000: nop
IL_0001: ldc.i4.6
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: call int32 CSharp.Extensions::Square(int32)
IL_0009: call void [mscorlib]System.Console::WriteLine(int32)
IL_000e: nop
IL_000f: ret
} // end of method Program::Main
我們發現原來extension method也沒什麼玄乎的,編繹器會將其編繹為對Square(i)的呼叫,原來就是靜態類中方法呼叫。
將Extension Method改為靜態方法,並在Main函式中直接呼叫
namespace CSharp
{
class Program
{
static void Main(string[] args)
{
int i = 6;
Console.WriteLine(Extensions.Square(i));
}
}
static class Extensions
{
public static int Square(this int i)
{
return i * i;
}
}
}
修改後的IL程式碼{
class Program
{
static void Main(string[] args)
{
int i = 6;
Console.WriteLine(Extensions.Square(i));
}
}
static class Extensions
{
public static int Square(this int i)
{
return i * i;
}
}
}
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 16 (0x10)
.maxstack 1
.locals init ([0] int32 i)
IL_0000: nop
IL_0001: ldc.i4.6
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: call int32 CSharp.Extensions::Square(int32)
IL_0009: call void [mscorlib]System.Console::WriteLine(int32)
IL_000e: nop
IL_000f: ret
} // end of method Program::Main
{
.entrypoint
// Code size 16 (0x10)
.maxstack 1
.locals init ([0] int32 i)
IL_0000: nop
IL_0001: ldc.i4.6
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: call int32 CSharp.Extensions::Square(int32)
IL_0009: call void [mscorlib]System.Console::WriteLine(int32)
IL_000e: nop
IL_000f: ret
} // end of method Program::Main
可以看到,兩種程式碼產生的IL程式碼一模一樣。
下面說下如何定義Extension Method,首先,Extension Method必須定義在普通的 static class內,這裡講的普通是static class不能為泛型(non-generic)或者內嵌(non-nested)的。其次,Extension Method的第一個引數必須為this + 型別 + 變數名。該引數指定了擁有該方法的型別為 this指定的型別。可能有的人會問,即然this指定的型別擁有,那麼可不可以使用型別的私有或受保護的成員?很遺憾,不能。記住,Extension Method僅僅是看起來像是一個型別的方法,但其實質上不是,它更像是靜態型別的靜態方法,事實上,它確實擁有靜態方法所具有的所有功能。
說完了這些,再說一下Extension Method的作用域,它是整個namespace可見的,並且可以通過using namespace來匯入其它名稱空間中的Extension Method. 匯入的擴導方法有沒有可能因為跟原型別的重名方法衝突而導致編繹失敗呢?不會。如果有同名的方法,Extension Method會出現在該方法Intellisense中的Parameter Help和Quick Info中,我們可以象呼叫過載函式一樣呼叫它。
最後再說一下Extension Method的結合順序,它是自左向右結合的,比如x有兩個Extension Method方法A,B,x.A().B()將被編繹為B(A(x)).
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-612015/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- C# 3.0 feature 1--Implicitly typed local variablesC#
- C# 3.0新功能C#
- methods
- There are 5 methods of index lookupIndex
- C# 9.0 終於來了, Top-level programs 和 Partial Methods 兩大新特性探究C#
- Stochastic Methods in Finance (1)ASTNaN
- Vue踩坑之旅——methodsVue
- bootstrap-select——Methodsboot
- [譯] part 17: golang 方法methodsGolang
- 【Java 8實戰】Extension MethodsJava
- Python 的 Magic Methods 指南Python
- Statistical Computing and Empirical Methods
- MonoDevelop 3.0 大幅改進 C# 程式碼自動完成MonodevC#
- java new featureJava
- C#與.NET入門之C# 8.0和.NET Core 3.0高階程式設計C#程式設計
- golang programming language study methods websocketGolangWeb
- Python socket.help Methods薦Python
- Methods with Variable Argument Lists (var-args)
- 7.89 FEATURE_DETAILSAI
- Feature homophily metric
- 焦點關注:Visual C# 3.0 新特性概覽(轉)C#
- 12c new feature
- 版本新特性(new feature)
- 《C# 8.0和.NET Core 3.0高階程式設計(第4版)》之“C# 與 .NET 入門 ”C#程式設計
- 簡單介紹Java String Methods(上)Java
- 簡單介紹Java String Methods(下)Java
- 外部js呼叫vue的methods中的方法JSVue
- tc39 proposal: Classes private methods and getter/setters
- 讀Zepto原始碼之fx_methods模組原始碼
- CDH5之Exhausted available authentication methodsH5AI
- [Javascript] Perform Set Operations using JavaScript Set MethodsJavaScriptORM
- Results of T2DFP and iT2DFP methods
- Feature Flag 功能釋出控制
- new feature ——>mysql to oracle MigrationMySqlOracle
- ORACLE 11G FLASHBACK FEATUREOracle
- Oracle Database Change Data Capture featureOracleDatabaseAPT
- A2A (SOUL-Quiz FeatureUI
- 【譯】Android Gradle 外掛 4.0.0 中 Feature-on-Feature 的依賴關係AndroidGradle