C# Extension Methods
2023-03-13
C# Extension Methods (擴充方法) 是一種極具彈性和可擴展性的技術,它可以為現有的 Type 添加新的方法,而不需要修改原本的 Type 所在的 Class。
說明
情境對話
範例
使用 Extension Methods 的方法是建立新的靜態類別 (例如 StringExtensions
),並且加入新的靜態方法 (例如 ToInt
),並且在此靜態方法的第一個參數,使用 this
關鍵字,指出要擴充的 Type。
public static class StringExtensions
{
public static int ToInt(this string str)
{
int result;
int.TryParse(str, out result);
return result;
}
}
string str = "123";
int intValue = str.ToInt();
public static class ListExtensions
{
public static bool IsNullOrEmpty<T>(this List<T> list)
{
return list == null || list.Count == 0;
}
}
List<int> list = null;
bool isNullOrEmpty = list.IsNullOrEmpty();
public static class DateTimeExtensions
{
public static string ToShortDate(this DateTime dateTime)
{
return dateTime.ToShortDateString();
}
}
DateTime dateTime = DateTime.Now;
string shortDate = dateTime.ToShortDate();
Linq 應用
C# 的 LINQ (Language Integrated Query) 是一種強大的工具,可以將資料查詢和轉換整合到 C# 程式碼中。而 Extension Methods 可以用來擴充 LINQ 操作,這樣可以讓我們在 LINQ 查詢中使用自定義方法,使 LINQ 的應用範圍更加靈活。
以下是一個範例,展示如何使用 Extension Methods 擴充 LINQ 的 Where()
Operator。
首先,我們需要創建一個靜態類別,包含我們要定義的 Extension Method。在這個例子中,我們定義了一個名為 WhereIf()
的方法,它接受一個 bool
值 condition
和一個 Func<TSource, bool>
委託 predicate
:
using System;
using System.Collections.Generic;
using System.Linq;
public static class LinqExtensions
{
public static IEnumerable<TSource> WhereIf<TSource>(
this IEnumerable<TSource> source,
bool condition,
Func<TSource, bool> predicate)
{
if (condition)
{
return source.Where(predicate);
}
else
{
return source;
}
}
}
在這個 Extension Method 中,我們首先檢查 condition
的值。如果為 true
,則使用 LINQ 的 Where()
Operator來過濾序列,並返回過濾後的結果。如果 condition
為 false
,則直接返回原始序列。
現在,我們可以在 LINQ 查詢中使用 WhereIf()
方法。例如:
List<int> numbers = new List<int>() { 1, 2, 3, 4, 5 };
bool condition = true;
int threshold = 3;
var result = numbers
.WhereIf(condition, n => n > threshold)
.Select(n => n * 10);
foreach (var item in result)
{
Console.WriteLine(item);
}
在這個範例中,我們創建了一個名為 numbers
的整數列表,並定義了一個名為 condition
的 bool
變數,以及一個名為 threshold
的閾值。
然後,我們使用 WhereIf()
方法來過濾列表,只保留大於 threshold
的元素,如果 condition
為 false
,則直接返回原始列表。最後,我們使用 Select()
將序列中的每個元素乘以 10。
總而言之 Extension Methods 可以讓我們更加靈活地擴展 LINQ Operator,這對於編寫可重用的 LINQ 查詢非常有用。
業界應用
在 C# Extension Methods | GitHub 的開源專案中,將各種實用但原生 C# 未提供的方法加入為 Extension Methods,以 Nuget 安裝之後,原本的 C# 就像是多了一對翅膀,寫起來如虎添翼更為行雲流水。
其中一個範例是原本 C# 有提供 Array 的 Exists 方法,但必須使用靜態類別的方式呼叫使用:
Array.Exists(new string[] { "Mercury", "Venus", "Earth", "Mars", "Jupiter"}, "Earth")
但在 C# Extension Methods 的 Array - Exists 則將它擴充為 Extensino Methods,只需要直接在 array instance 上使用即可,用起來直觀也易於理解 😀
new string[] { "Mercury", "Venus", "Earth", "Mars", "Jupiter"}.Exists("Earth");
C# Extension Methods - Array - Exists.cs
public static partial class Extensions
{
/// <summary>
/// A T[] extension method that exists.
/// </summary>
/// <typeparam name="T">Generic type parameter.</typeparam>
/// <param name="array">The array to act on.</param>
/// <param name="match">Specifies the match.</param>
/// <returns>true if it succeeds, false if it fails.</returns>
public static Boolean Exists<T>(this T[] array, Predicate<T> match)
{
return Array.Exists(array, match);
}
}