➕ افزودن Static Extension Member به Typeها
ءStatic extensionها به شما اجازه میدهند بهجای instance، مستقیماً به خود type متد یا property اضافه کنید.
این نوع extension برای factory methodها 🏭 یا utility functionها 🧰 بسیار کاربردی است.
برای ساخت static extension، از extension بدون نامگذاری receiver استفاده میکنیم 👇
public static class ProductExtensions
{
extension(Product)
{
public static Product CreateDefault() =>
new Product
{
Name = "Unnamed Product",
Price = 0,
StockQuantity = 0,
Category = "Uncategorized",
CreatedDate = DateTime.UtcNow
};
public static bool IsValidPrice(decimal price) =>
price >= 0 && price <= 1000000;
public static string DefaultCategory => "General";
}
}
حالا میتوانی این memberهای static را مستقیماً روی خود type صدا بزنی 👇
var product = Product.CreateDefault();
if (Product.IsValidPrice(999.99m))
{
product.Price = 999.99m;
}
🧬 کار با Generics و Type Constraintها
ءGeneric extensionها به شما اجازه میدهند کدی بنویسید که با چندین type کار کند.
این موضوع بهخصوص هنگام کار با collectionها یا interfaceها بسیار مفید است 📦
بیایید <IEnumerable<T را extend کنیم و قابلیت فیلتر و تبدیل اضافه کنیم 👇
public static class EnumerableExtensions
{
extension<T>(IEnumerable<T> source)
{
public IEnumerable<T> WhereNotNull() =>
source.Where(item => item != null);
public Dictionary<TKey, List<T>> GroupToDictionary<TKey>(
Func<T, TKey> keySelector) where TKey : notnull =>
source.GroupBy(keySelector)
.ToDictionary(g => g.Key, g => g.ToList());
}
}
اینجا از constraint زیر استفاده شده 👇
where TKey : notnull
📌 این تضمین میکند که کلید دیکشنری مقدار null نداشته باشد.
حالا میتوانی این extensionها را بهراحتی با LINQ chain کنی 🔗
var products = _productService.GetAll();
var productsByCategory = products
.WhereNotNull()
.Where(p => p.IsAvailable)
.GroupToDictionary(p => p.Category);
foreach (var category in productsByCategory)
{
Console.WriteLine($"{category.Key}: {category.Value.Count} products");
}
🔢 ءExtension با Constraint عددی
میتوانی constraint تعریف کنی تا extension فقط روی typeهای خاصی کار کند.
مثلاً این extension فقط روی typeهای عددی که <INumber<T را پیادهسازی کردهاند کار میکند 🧮
public static class NumericExtensions
{
extension<T>(IEnumerable<T> source)
where T : INumber<T>
{
public T Sum()
{
var total = T.Zero;
foreach (var item in source)
{
total += item;
}
return total;
}
public T Average()
{
var enumerable = source.ToList();
var sum = enumerable.Sum();
var count = T.CreateChecked(enumerable.Count);
return sum / count;
}
public IEnumerable<T> GreaterThan(T threshold) =>
source.Where(x => x > threshold);
}
}
این extension با هر type عددی سازگار است 👇
var prices = new[] { 10.99m, 25.50m, 5.00m, 15.75m };
var expensiveItems = prices.GreaterThan(15.00m);
var averagePrice = prices.Average();