跳過到頁腳內容
Iron Academy Logo
學習 C#
學習 C#

其他分類

理解方法和使用 C# 擴展方法

Tim Corey
28m 27s

在C#程式設計中,方法是封裝可重用程式碼並執行特定任務的重要構建塊。 它們可以接受參數、返回值,並通過重載來處理不同的輸入。 更高級的概念是,擴充方法使開發者能夠向現有類型添加功能,包括那些他們無法控制的類型。

Tim Corey 的影片 '如何在C#中創建擴充方法' 是一個很好的資源。 在本指南中,我們將探討Tim涵蓋的幾個主題:

  1. 定義和調用方法
  2. 方法參數和引數
  3. 方法回傳值
  4. 方法重載
  5. 實現擴充方法

定義和調用方法

實例方法的定義

在C#中,一個方法是在類內定義的。 方法定義的一般語法包括訪問修飾符、返回類型、方法名和參數。

public class SampleClass
{
    public void SampleMethod()
    {
        // Method implementation  
    }
}
public class SampleClass
{
    public void SampleMethod()
    {
        // Method implementation  
    }
}

在4:05的Tim Corey's示例中,他在一個靜態類中定義了一個方法以創建擴充方法。 定義的方法是 PrintToConsole。 定義包含了所有一般語法,清晰地解釋了如何用一個實用的例子來定義一個方法:

public static class Extensions
{
    public static void PrintToConsole(this string message)
    {
        Console.WriteLine(message);
    }
}
public static class Extensions
{
    public static void PrintToConsole(this string message)
    {
        Console.WriteLine(message);
    }
}

調用方法

'方法調用'是告訴程式執行在程式碼的其它地方定義的特定方法,執行一個預定義的動作。 方法是通過類實例調用的,或者如果它們是靜態方法,則直接調用。 對於擴充方法,它們看起來就像是它們所擴展類型的一部分。 在視頻的6:18,Tim展示了如何像預定義方法一樣用基本數據類型調用一個擴充方法。

string demo = "This is a demo";
demo.PrintToConsole(); // Extension method call
string demo = "This is a demo";
demo.PrintToConsole(); // Extension method call

方法參數和引數

參數

參數是在方法定義中指定的,作為傳遞到方法中的值的佔位符。 您可以在這裡看到在調用 WriteLine 方法後,而 message 是參數。

public void DisplayMessage(string message)
{
    Console.WriteLine(message);
}
public void DisplayMessage(string message)
{
    Console.WriteLine(message);
}

另外,在Tim Corey在4:05給出的擴充方法示例中,message 是參數:

public static void PrintToConsole(this string message)
{
    Console.WriteLine(message);
}
public static void PrintToConsole(this string message)
{
    Console.WriteLine(message);
}

引數

引數是調用方法時實際傳遞給方法的值。

DisplayMessage("Hello, World!"); // "Hello, World!" is the argument
DisplayMessage("Hello, World!"); // "Hello, World!" is the argument

當Tim Corey在6:20調用該方法時使用字串類型的點語法時,字串值實際上作為值傳遞給 PrintToConsole 方法:

string demo = "This is a demo";
demo.PrintToConsole(); // "This is a demo" is the argument
string demo = "This is a demo";
demo.PrintToConsole(); // "This is a demo" is the argument

方法回傳值

方法可以使用return語句返回值。 返回類型是在方法簽名中指定的。

public int Add(int a, int b)
{
    return a + b;
}
public int Add(int a, int b)
{
    return a + b;
}

雖然Tim Corey的視頻中的擴充方法沒有返回值(void返回類型),但您可以創建帶返回值的擴充方法。 Tim的示例中的返回類型是void,這意味著該方法不返回任何值。 以下示例顯示如何返回一個值:

public static int WordCount(this string str)
{
    return str.Split(' ').Length;
}
public static int WordCount(this string str)
{
    return str.Split(' ').Length;
}

方法重載 (11:15)

方法重載允許多個具有相同名稱但不同參數的方法存在。 這對創建靈活且直觀的API很有用。

public void Display(string message)
{
    Console.WriteLine(message);
}

public void Display(int number)
{
    Console.WriteLine(number);
}
public void Display(string message)
{
    Console.WriteLine(message);
}

public void Display(int number)
{
    Console.WriteLine(number);
}

Tim Corey在11:24簡要介紹了為不同日誌場景創建多個方法,這可以被視為更廣泛意義上的方法重載示例。 日誌方法存在兩次,一個帶一個參數,另一個有兩個參數。 在11:39的第二個日誌方法是日誌方法的重載版本,賦予它多種功能,在相同名稱下。

Implementing Extension Methods in C

什麼是擴充方法? (3:13)

擴充方法允許您向現有類型添加新方法,而無需修改或重新編譯它們。 雖然它們被調用時就像實例方法一樣,但擴充方法是定義為靜態的。

創建擴充方法

在前一節中'定義和調用方法',我們強調了如何在一個單獨的靜態類中創建一個擴充方法,並在其中定義靜態方法以用作擴充方法。 以下是Tim Corey強調的一些關鍵點:

  1. 確保定義一個單獨的公共靜態類,或者,如Tim所說,"將類標記為靜態,否則它將無法工作。"
  2. 當您創建更多的擴充方法時,按類型分組它們 (3:43)
  3. 定義一個靜態方法,第一個參數前綴 this 關鍵字,指定要擴展的類型 (4:58)
public static class Extensions
{
    public static void PrintToConsole(this string message)
    {
        Console.WriteLine(message);
    }
}
public static class Extensions
{
    public static void PrintToConsole(this string message)
    {
        Console.WriteLine(message);
    }
}

調用擴充方法 (6:18)

接下來,Tim展示了如何在這個字串變數上調用擴充方法:

demo.PrintToConsole();
demo.PrintToConsole();

當您輸入 demo 並開始鍵入 Print 時,IntelliSense會建議 PrintToConsole 方法。 這是添加到 string 類型的新方法。

方法調用如何工作 (6:30)

Tim解釋為何您可以調用 demo.PrintToConsole()

  • Demo是一個字串類型:變數 demostring 的類型。
  • 擴展字串類型string 類型已通過新方法 PrintToConsole 進行擴展。

理解參數 (6:41)

儘管似乎未向 PrintToConsole 方法傳遞任何參數,但Tim指出隱式參數傳遞 - demo 字串作為擴充方法的第一個參數傳遞。

Tim強調擴充方法在調用時比其定義時少了一個參數。 這是因為第一個參數(被擴展的類型)是隱式的。

擴充方法的簽名

這裡,this string message 意味著方法擴展了 string 類型,message 是隱式參數:

public static void PrintToConsole(this string message)
public static void PrintToConsole(this string message)

執行程式碼 (7:08)

最後,當調用方法 PrintToConsole 時,它將字串輸出到控制台:

Console.WriteLine(message);
Console.WriteLine(message);

因此,調用 demo.PrintToConsole() 會將 "這是一個展示" 印到控制台。

對第三方類使用擴充方法

擴展第三方類 (10:59)

Tim Corey解釋說擴充方法可以擴展任何類型,即使是您無法直接修改的第三方類別。 例如,讓我們看看在11:09的 SimpleLogger 類。

這裡,Tim使用假設的第三方類 SimpleLogger 記錄消息到控制台 (11:09)。 該類有兩個方法:

public class SimpleLogger
{
    public void Log(string message)
    {
        Console.WriteLine(message);
    }

    public void Log(string message, string messageType)
    {
        Console.WriteLine($"{messageType}: {message}");
    }
}
public class SimpleLogger
{
    public void Log(string message)
    {
        Console.WriteLine(message);
    }

    public void Log(string message, string messageType)
    {
        Console.WriteLine($"{messageType}: {message}");
    }
}

這些方法不太理想,因為消息類型是一個簡單的字串,這可能導致不一致。 Tim建議創建擴充方法以改進該類。

實現一致的消息類型

使用擴充方法能確保持續性地使用相同的消息類型和格式,提高代碼一致性。 在(12:40),Tim創建了一個靜態類 ExtendSimpleLogger

public static class ExtendSimpleLogger
{
    public static void LogError(this SimpleLogger logger, string message)
    {
        logger.Log(message, "Error");
    }

    public static void LogWarning(this SimpleLogger logger, string message)
    {
        logger.Log(message, "Warning");
    }
}
public static class ExtendSimpleLogger
{
    public static void LogError(this SimpleLogger logger, string message)
    {
        logger.Log(message, "Error");
    }

    public static void LogWarning(this SimpleLogger logger, string message)
    {
        logger.Log(message, "Warning");
    }
}

使調用更一致

手頭上有此程式 (14:02),他現在可以在 SimpleLogger 實例上調用擴充方法:

SimpleLogger logger = new SimpleLogger();
logger.LogError("This is an error");
logger.LogWarning("This is a warning");
SimpleLogger logger = new SimpleLogger();
logger.LogError("This is an error");
logger.LogWarning("This is a warning");

這確保了消息類型始終是'錯誤'和'警告'。

增強輸出格式 (14:35)

Tim增加功能以設置錯誤消息的控制台文字顏色,確保它們突出顯示:

public static void LogError(this SimpleLogger logger, string message)
{
    var defaultColor = Console.ForegroundColor;
    Console.ForegroundColor = ConsoleColor.Red;
    logger.Log(message, "Error");

    Console.ForegroundColor = defaultColor;
}
public static void LogError(this SimpleLogger logger, string message)
{
    var defaultColor = Console.ForegroundColor;
    Console.ForegroundColor = ConsoleColor.Red;
    logger.Log(message, "Error");

    Console.ForegroundColor = defaultColor;
}

與直接方法調用進行比較 (17:21)

Tim將此方法與直接調用原始 Log 方法進行比較,這可能會導致不一致:

logger.Log("Test error", "Error");
logger.Log("Another error", "ERROR");
logger.Log("Test error", "Error");
logger.Log("Another error", "ERROR");

此方法容易出現拼寫錯誤和不一致的格式。

鏈接擴充方法 (18:13)

Tim演示了如何鏈接擴充方法以使代碼更具可讀性:

public static void LogInfo(this SimpleLogger logger, string message)
{
    logger.Log(message, "Info");
}

public static void SaveToDatabase(this SimpleLogger logger)
{
    // Simulate saving to a database
}
public static void LogInfo(this SimpleLogger logger, string message)
{
    logger.Log(message, "Info");
}

public static void SaveToDatabase(this SimpleLogger logger)
{
    // Simulate saving to a database
}

現在,您可以鏈接這些方法:

logger.LogInfo("Information").SaveToDatabase();
logger.LogInfo("Information").SaveToDatabase();

與嵌套方法調用相比,這使得代碼更易讀和直觀:

SaveToDatabase(LogInfo(logger, "Information"));
SaveToDatabase(LogInfo(logger, "Information"));

通過使用點符號和鏈接,代碼的意圖變得更清晰且不那麼嵌套。

擴展您不擁有的事物

在20:13,Tim Corey解釋擴充方法非常適合添加功能到您不擁有的類,如第三方函式庫。 這允許無需修改原始代碼進行增強。

避免依賴

Corey也強調使用擴充方法引入依賴而不將它們直接與類耦合。 例如,添加數據庫保存功能到 Person 類,而不嵌入數據庫邏輯。

擴展介面

擴充方法也可以應用於介面,如21:30所述,使實現該介面的多個類可以共享相同的功能。 這促進了代碼重複使用和簡化。

何時不使用擴充方法

在23:03,Tim Corey建議避免過度使用擴充方法,尤其是與基本或由Microsoft提供的類型,以防止混亂和複雜性。 謹慎使用,僅在有明顯好處時使用。

開放/封閉原則

在24:54-25:40之間的部分中,Tim強調通過使用擴充方法來遵循開放/封閉原則,從而在不修改現有穩定代碼的情況下增加新功能,從而減少引入錯誤的風險。

使用語句的最佳實踐

通過合乎邏輯的分組來組織擴充方法,並將其放置在單獨的命名空間中,以避免命名衝突並促進更易於維護和調試。

結論

這裡您就了解了定義與調用方法,處理參數和回傳值並利用方法重載的基礎知識。 藉此,您可以在C#中構建強大而靈活的應用程式。

如Tim Corey所解釋,擴充方法提供了一種強大方式來增強現有類型,並使您的代碼更加可讀和易於維護。 有關更詳細的見解和實際範例,您可以觀看Tim Corey的完整視頻 如何在C#中創建擴充方法

Hero Worlddot related to 理解方法和使用 C# 擴展方法
Hero Affiliate related to 理解方法和使用 C# 擴展方法

通過分享您所愛的東西賺得更多

您是否在為使用.NET、C#、Java、Python或Node.js的開發者創建內容?將您的專業知識轉化為額外收入!

鋼鐵支援團隊

我們每週 5 天,每天 24 小時在線上。
聊天
電子郵件
打電話給我