首頁 後端開發 C#.Net教程 C# 參數帶this是什麼意思(擴充方法)

C# 參數帶this是什麼意思(擴充方法)

Feb 18, 2017 am 10:24 AM
c# this


擴展方法使你能夠向現有類型「添加」方法,而無需創建新的派生類型、重新編譯或以其他方式修改原始類型。 擴充方法是一種特殊的靜態方法,但可以像擴充類型上的實例方法一樣進行呼叫。  對於 C# 和 Visual Basic 編寫的客戶端程式碼,呼叫擴充方法與呼叫在型別中實際定義的方法之間沒有明顯的差異。

最常見的擴充方法是 LINQ 標準查詢運算符,它將查詢功能加入現有的 System.Collections.IEnumerable 和 System.Collections.Generic.IEnumerable 類型。 若要使用標準查詢運算符,請先使用 using System.Linq 指令將它們置於範圍中。  然後,任何實作了 IEnumerable 的型別看起來都具有 GroupBy、OrderBy、Average 等實例方法。  在 IEnumerable類型的實例(如 List 或 Array)後鍵入「dot」時,可以在 IntelliSense 語句完成中看到這些附加方法。

下面的範例示範如何對一個整數陣列呼叫標準查詢運算子 OrderBy 方法。 括號裡面的表達式是一個 lambda 表達式。  很多標準查詢運算子採用 lambda 運算式作為參數,但這不是擴充方法的必要條件。  有關詳細信息,請參閱 Lambda 表達式(C# 程式指南)。

C#



class ExtensionMethods2    
{    static void Main()
    {            
        int[] ints = { 10, 45, 15, 39, 21, 26 };        var result = ints.OrderBy(g => g);        foreach (var i in result)
        {
            System.Console.Write(i + " ");
        }           
    }        
}//Output: 10 15 21 26 39 45
登入後複製


擴充方法被定義為靜態方法,但它們是透過實例語法進行語法進行的調用。 它們的第一個參數指定方法作用於哪個類型,並且該參數以 this 修飾符為前綴。  只有當你使用 using 指令將命名空間明確匯入到原始碼之後,擴充方法才位於範圍中。

下面的範例示範為 System.String 類別定義的一個擴充方法。 請注意,它是在非巢狀的、非泛型靜態類別內部定義的:

C#


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


於範圍中:

using ExtensionMethods;
登入後複製

而且,可以使用以下语法从应用程序中调用该扩展方法:

string s = "Hello Extension Methods";
int i = s.WordCount();
登入後複製


在代码中,可以使用实例方法语法调用该扩展方法。 但是,编译器生成的中间语言 (IL) 会将代码转换为对静态方法的调用。 因此,并未真正违反封装原则。 实际上,扩展方法无法访问它们所扩展的类型中的私有变量。

有关详细信息,请参阅如何:实现和调用自定义扩展方法(C# 编程指南)。

通常,你更多时候是调用扩展方法而不是实现你自己的扩展方法。 由于扩展方法是使用实例方法语法调用的,因此不需要任何特殊知识即可从客户端代码中使用它们。 若要为特定类型启用扩展方法,只需为在其中定义这些方法的命名空间添加 using 指令。 例如,若要使用标准查询运算符,请将此 using 指令添加到代码中:


using System.Linq;
登入後複製


(你可能还必须添加对 System.Core.dll 的引用。)你将注意到,标准查询运算符现在作为可供大多数 IEnumerable 类型使用的附加方法显示在 IntelliSense 中。

C# 參數帶this是什麼意思(擴充方法)C# 參數帶this是什麼意思(擴充方法)

尽管标准查询运算符没有显示在 String 的 IntelliSense 中,但它们仍然可用。


在編譯時綁定擴充方法

可以使用擴充方法來擴充類別或接口,但不能重寫擴充方法。 與介面或類別方法具有相同名稱和簽署的擴充方法永遠不會被呼叫。  編譯時,擴充方法的優先權總是比型別本身定義的實例方法低。  換句話說,如果某一型別有一個名為 Process(int i) 的方法,而你有一個相同簽章的擴充方法,則編譯器總是綁定到該實例方法。  當編譯器遇到方法呼叫時,它首先在該類型的實例方法中尋找匹配的方法。  如果未找到任何匹配方法,編譯器將搜尋為該類型定義的任何擴充方法,並且綁定到它找到的第一個擴充方法。  下面的範例示範編譯器如何決定要綁定到哪個擴充方法或實例方法。

範例

下面的範例示範 C# 編譯器在決定是將方法呼叫綁定到類型上的實例方法或綁定到擴充方法時所遵循的規則。 靜態類別 Extensions 包含為任何實作了 IMyInterface 的類型定義的擴充方法。  類 AB 和 C 都實現了這個介面。

MethodB 擴充方法永遠不會被調用,因為它的名稱和簽章與這些類別已經實現的方法完全匹配。

如果編譯器找不到具有匹配簽章的實例方法,它會綁定到匹配的擴充方法(如果有這樣的方法)。

C#


// Define an interface named IMyInterface.namespace DefineIMyInterface
{    using System;    public interface IMyInterface
    {        // Any class that implements IMyInterface must define a method
        // that matches the following signature.
        void MethodB();
    }
}// Define extension methods for IMyInterface.namespace Extensions
{    using System;    using DefineIMyInterface;    // The following extension methods can be accessed by instances of any 
    // class that implements IMyInterface.
    public static class Extension
    {        public static void MethodA(this IMyInterface myInterface, int i)
        {
            Console.WriteLine
                ("Extension.MethodA(this IMyInterface myInterface, int i)");
        }        public static void MethodA(this IMyInterface myInterface, string s)
        {
            Console.WriteLine
                ("Extension.MethodA(this IMyInterface myInterface, string s)");
        }        // This method is never called in ExtensionMethodsDemo1, because each 
        // of the three classes A, B, and C implements a method named MethodB
        // that has a matching signature.
        public static void MethodB(this IMyInterface myInterface)
        {
            Console.WriteLine
                ("Extension.MethodB(this IMyInterface myInterface)");
        }
    }
}// Define three classes that implement IMyInterface, and then use them to test// the extension methods.namespace ExtensionMethodsDemo1
{    using System;    using Extensions;    using DefineIMyInterface;    class A : IMyInterface
    {        public void MethodB() { Console.WriteLine("A.MethodB()"); }
    }    class B : IMyInterface
    {        public void MethodB() { Console.WriteLine("B.MethodB()"); }        
    public void MethodA(int i) { Console.WriteLine("B.MethodA(int i)"); }
    }    class C : IMyInterface
    {        public void MethodB() { Console.WriteLine("C.MethodB()"); }        
    public void MethodA(object obj)
        {
            Console.WriteLine("C.MethodA(object obj)");
        }
    }    class ExtMethodDemo
    {        static void Main(string[] args)
        {            // Declare an instance of class A, class B, and class C.
            A a = new A();
            B b = new B();
            C c = new C();            // For a, b, and c, call the following methods:
            //      -- MethodA with an int argument
            //      -- MethodA with a string argument
            //      -- MethodB with no argument.

            // A contains no MethodA, so each call to MethodA resolves to 
            // the extension method that has a matching signature.
            a.MethodA(1);           // Extension.MethodA(object, int)
            a.MethodA("hello");     // Extension.MethodA(object, string)

            // A has a method that matches the signature of the following call
            // to MethodB.
            a.MethodB();            // A.MethodB()

            // B has methods that match the signatures of the following
            // method calls.
            b.MethodA(1);           // B.MethodA(int)
            b.MethodB();            // B.MethodB()

            // B has no matching method for the following call, but 
            // class Extension does.
            b.MethodA("hello");     // Extension.MethodA(object, string)

            // C contains an instance method that matches each of the following
            // method calls.
            c.MethodA(1);           // C.MethodA(object)
            c.MethodA("hello");     // C.MethodA(object)
            c.MethodB();            // C.MethodB()
        }
    }
}/* Output:
    Extension.MethodA(this IMyInterface myInterface, int i)
    Extension.MethodA(this IMyInterface myInterface, string s)
    A.MethodB()
    B.MethodA(int i)
    B.MethodB()
    Extension.MethodA(this IMyInterface myInterface, string s)
    C.MethodA(object obj)
    C.MethodA(object obj)
    C.MethodB()
 */
登入後複製

通用准则

通常,建议你只在不得已的情况下才实现扩展方法,并谨慎地实现。 只要有可能,必须扩展现有类型的客户端代码都应该通过创建从现有类型派生的新类型来达到这一目的。 有关详细信息,请参阅继承(C# 编程指南)。

在使用扩展方法来扩展你无法更改其源代码的类型时,你需要承受该类型实现中的更改会导致扩展方法失效的风险。

如果你确实为给定类型实现了扩展方法,请记住以下几点:

  • 如果扩展方法与该类型中定义的方法具有相同的签名,则扩展方法永远不会被调用。

  • 在命名空间级别将扩展方法置于范围中。 例如,如果你在一个名为 Extensions 的命名空间中具有多个包含扩展方法的静态类,则这些扩展方法将全部由 using Extensions; 指令置于范围中。

针对已实现的类库,不应为了避免程序集的版本号递增而使用扩展方法。 如果要向你拥有源代码的库中添加重要功能,应遵循适用于程序集版本控制的标准 .NET Framework 准则。 有关详细信息,请参阅程序集版本控制。

 以上就是C# 参数带this是什么意思(扩展方法)的内容,更多相关内容请关注PHP中文网(www.php.cn)!


本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1677
14
CakePHP 教程
1431
52
Laravel 教程
1334
25
PHP教程
1280
29
C# 教程
1257
24
使用 C# 的活動目錄 使用 C# 的活動目錄 Sep 03, 2024 pm 03:33 PM

使用 C# 的 Active Directory 指南。在這裡,我們討論 Active Directory 在 C# 中的介紹和工作原理以及語法和範例。

C# 中的隨機數產生器 C# 中的隨機數產生器 Sep 03, 2024 pm 03:34 PM

C# 隨機數產生器指南。在這裡,我們討論隨機數產生器的工作原理、偽隨機數和安全數的概念。

C# 資料網格視圖 C# 資料網格視圖 Sep 03, 2024 pm 03:32 PM

C# 資料網格視圖指南。在這裡,我們討論如何從 SQL 資料庫或 Excel 檔案載入和匯出資料網格視圖的範例。

C# 中的階乘 C# 中的階乘 Sep 03, 2024 pm 03:34 PM

C# 階乘指南。這裡我們討論 C# 中階乘的介紹以及不同的範例和程式碼實作。

c#多線程和異步的區別 c#多線程和異步的區別 Apr 03, 2025 pm 02:57 PM

多線程和異步的區別在於,多線程同時執行多個線程,而異步在不阻塞當前線程的情況下執行操作。多線程用於計算密集型任務,而異步用於用戶交互操作。多線程的優勢是提高計算性能,異步的優勢是不阻塞 UI 線程。選擇多線程還是異步取決於任務性質:計算密集型任務使用多線程,與外部資源交互且需要保持 UI 響應的任務使用異步。

C# 中的模式 C# 中的模式 Sep 03, 2024 pm 03:33 PM

C# 模式指南。在這裡,我們討論 C# 中模式的介紹和前 3 種類型,以及其範例和程式碼實作。

C# 中的質數 C# 中的質數 Sep 03, 2024 pm 03:35 PM

C# 質數指南。這裡我們討論c#中素數的介紹和範例以及程式碼實作。

xml怎麼改格式 xml怎麼改格式 Apr 03, 2025 am 08:42 AM

可以採用多種方法修改 XML 格式:使用文本編輯器(如 Notepad )進行手工編輯;使用在線或桌面 XML 格式化工具(如 XMLbeautifier)進行自動格式化;使用 XML 轉換工具(如 XSLT)定義轉換規則;或者使用編程語言(如 Python)進行解析和操作。修改時需謹慎,並備份原始文件。

See all articles