ایندکسرهای الحاقی (Extension Indexers) در C# 15
نویسنده: وحید نصیری
تاریخ: ۱۴۰۵/۰۵/۲۰ ۰۹:۳۵
آدرس: www.dntips.ir
چکیده: با تکامل روزافزون زبان سیشارپ (#C)، ویژگی اعضای الحاقی (Extension Members) گامهای بزرگی به سمت بهبود قابلیت خوانایی و بیانگری کد برداشته است. پس از ارتقای اعضای الحاقی در نسخههای اخیر، نسخه C# 15 قابلیت جدیدی تحت عنوان ایندکسرهای الحاقی (Extension Indexers) را معرفی کرده است. این ویژگی به توسعهدهندگان اجازه میدهد بدون دستکاری سورسکد اصلی یا دسترسی به تعریف یک نوع (Type)، نحوه دسترسی شاخصی (Syntax []) را برای انواع موجود فراهم کنند. این مقاله به بررسی ساختار سینتکسی، نحوه اعلان، تحلیل فنی زیرساختی، ملاحظات عملکردیو بهترین الگوی مصرف این قابلیت جدید در اکوسیستم داتنت میپردازد.[index] را روی انواعی که فاقد ایندکسر داخلی هستند (مانند IEnumerable) میسر میسازد. با این حال، این زیباسازی سینتکسی (Syntactic Sugar) خطرات ناخواستهای مانند پنهانسازی پیچیدگی الگوریتمی دارد که آگاهی عمیق توسعهدهنده از زیرساخت اجرایی را میطلبد.using System;
using System.Collections.Generic;
using System.Linq;
namespace CSharp15Features
{
public static class SequenceIndexerExtensions
{
// تعریف بلوک توسعه روی IEnumerable<int> به همراه نام پارامتر receiver (sequence)
extension(IEnumerable<int> sequence)
{
// تعریف ایندکسر فقط-خواندنی (Get-only Indexer)
public int this[int index] => sequence.ElementAt(index);
}
}
}using کردن فضای نام مربوطه، توسعهدهنده میتواند بدون فراخوانی مستقیم متدهای LINQ، از سینتکس بومی ایندکسر استفاده کند:IEnumerable<int> numbers = Enumerable.Range(1, 10); // فراخوانی ایندکسر توسعه دقیقا مشابه یک ایندکسر ذاتی روی نوع int thirdElement = numbers[2]; Console.WriteLine(thirdElement); // خروجی: 3
IList یا آرایه، دسترسی به یک عنصر از طریق ایندکسر دارای پیچیدگی زمانی O(1) است. اما در IEnumerable که فاقد ایندکس داخلی است، کد بالا درون خود متد LINQ ElementAt را صدا میزند.ElementAt باید دنباله را پیمایش کند تا به عنصر مورد نظر برسد؛ یعنی پیچیدگی اجرای numbers[900000] برابر با O(N) خواهد بود.IEnumerable، بررسیهای نوعی (Pattern Matching یا Type Casting) صورت گیرد تا در صورت پشتیبانی ساختار زیرین از IReadOnlyList یا IList، دسترسی مستقیم O(1) اعمال شود:public static class EnumerableExtensions
{
extension<T>(IEnumerable<T> sequence)
{
public T this[int index]
{
get
{
// بهینهسازی: اگر ساختار داده از قبل Indexable است، سریعاً دسترسی مستقیم داده شود
if (sequence is IReadOnlyList<T> readOnlyList)
return readOnlyList[index];
if (sequence is IList<T> list)
return list[index];
// در غیر این صورت، پیمایش LINQ انجام میشود (O(N))
return sequence.ElementAt(index);
}
}
}
}