آموزش گام‌به‌گام #C (جلسه یازدهم: اندیس گذار یا indexerها)
1398/01/10 11:09 , میلاد صاحب نظر

آموزش گام‌به‌گام #C (جلسه یازدهم: اندیس گذار یا indexerها)

گاهی ممکن است پیاده‌سازی و استفاده از آرایه‌ها مشکل باشد یا در مواردی شاید حتی غیر ممکن باشد. اما اگر حتما لازم باشد از کارایی آرایه استفاده کنید آن موقع چه می‌کنید؟ Indexerها راه حل شما هستند. با ما همراه باشید.

جلسه اول: آغاز کار با #C جلسه ششم: namespaceها جلسه یازدهم: اندیس گذار یا indexerها جلسه شانزدهم: استفاده از اتریبیوت‌ها جلسه بیست و یکم: متدهای بی‌نام یا anonymous
جلسه دوم: عملگرها، نوع‌ها و متغیرها جلسه هفتم: مقدمه‌ای بر کلاس‌های #C جلسه دوازدهم: ساختار یا structها جلسه هفدهم: enumها جلسه بیست و دوم: موضوعاتی در مورد نوع در #C
جلسه سوم: عبارات کنترلی - گزینشی جلسه هشتم: وراثت کلاس در #C جلسه سیزدهم: واسط یا interfaceها جلسه هجدهم: عملگرهای overloading جلسه بیست و سوم: کار با نوع‌های nullable
جلسه چهارم: عبارات کنترلی - حلقه‌ها جلسه نهم: چندریختی جلسه چهاردهم: مقدمه‌ای بر delegateها و رویدادها جلسه نوزدهم: کپسوله‌سازی  
جلسه پنجم: متدها جلسه دهم: ویژگی یا propertyها جلسه پانزدهم: مقدمه‌ای بر کنترل خطا یا exception جلسه بیستم: مقدمه‌ای بر generic collectionها  

در این جلسه در مورد اندیس گذار یا indexerها در #C صحبت می‌کنیم. اهداف ما در این جلسه عبارت‌اند از:

  • درک عملکرد و کارایی indexerها.
  • پیاده‌سازی یک indexer.
  • overload کردن indexerها.
  • درک چگونگی پیاده‌سازی indexerهای چند پارامتری.

Indexerها باعث می‌شوند بتوانید از کلاس خود دقیقا همانند یک آرایه استفاده کنید. در داخل یک کلاس، شما مجموعه‌ای از مقادیر را به هر روشی که بخواهید، می‌توانید مدیریت کنید. این اشیاء می‌توانند مجموعه محدودی از اعضای کلاس، یک آرایه دیگر یا چند ساختمان داده پیچیده باشند.

بدون توجه به نوع پیاده‌سازی درون کلاس، داده‌های کلاس را می‌توان دائما با استفاده از indexerها به دست آورد. در ادامه یک مثال مشاهده می‌کنید.

لیست ۱-۱۱. نمونه‌ای از یک indexer. IntIndexer.cs

using System;

/// <summary>
///     ساده indexer نمونه‌ای از یک.
/// </summary>
class IntIndexer
{
    private string[] myData;

    public IntIndexer(int size)
    {
        myData = new string[size];

        for (int i=0; i < size; i++)
        {
            myData[i] = "empty";
        }
    }

    public string this[int pos]
    {
        get
       {
            return myData[pos];
        }
        set
       {
            myData[pos] = value;
        }
    }

    static void Main(string[] args)
    {
        int size = 10;

        IntIndexer myInd = new IntIndexer(size);

        myInd[9] = "Some Value";
        myInd[3] = "Another Value";
        myInd[5] = "Any Value";

        Console.WriteLine("\nIndexer Output\n");

        for (int i=0; i < size; i++)
        {
            Console.WriteLine("myInd[{0}]: {1}", i, myInd[i]);
        }
    }
}

لیست ۱-۱۱ نحوه پیاده‌سازی یک Indexer را نشان می‌دهد. کلاس IntIndexer دارای یک آرایه از نوع رشته به نام myData است. myData یک آرایه Private است که کاربران خارجی نمی‌توانند آن را ببینند. این آرایه در constructor مقداردهی اولیه شده است، که همان‌طور که مشاهده می‌کنید یک پارامتر size از نوع int گرفته است.

سپس آرایه myData نمونه‌سازی شده است و همه عناصر آن با کلمه “empty” پر شده‌اند.

عضو بعدی کلاس، Indexer است که با کلید واژه this و کروشه باز و بسته تعریف شده است ([this[int pos). این Indexer فقط یک پارامتر موقعیت به نام pos می‌پذیرد.

همان‌طور که احتمالا حدس زده‌اید، پیاده‌سازی یک Indexer دقیقا همانند پیاده‌سازی یک property است. Indexer نیز دارای accessorهای get و set است که دقیقا همانند accessorهای یک property عمل می‌کنند. این Indexer یک رشته بازمی‌گرداند که در قسمت تعریف Indexer با یک مقدار بازگشتی String یا رشته نمایش داده شده است.

متد ()Main خیلی ساده یک شیء IntIndexer را نمونه‌سازی می‌کند، چند مقدار به آن اضافه می‌کند و نتایج را چاپ می‌کند. خروجی به این شکل است:

Indexer Output

myInd[0]: empty
myInd[1]: empty
myInd[2]: empty
myInd[3]: Another Value
myInd[4]: empty
myInd[5]: Any Value
myInd[6]: empty
myInd[7]: empty
myInd[8]: empty
myInd[9]: Some Value

در بسیاری از زبان‌ها، روش مرسوم برای دسترسی به آرایه‌ها، استفاده از یک Integer است، اما Indexer تا در #C فراتر از این موضوع رفته‌اند. Indexerها می‌توانند با چندین پارامتر تعریف شوند و هر پارامتر می‌تواند از نوع متفاوت باشد.

پارامترهای اضافی توسط ویرگول از هم جدا می‌شوند، درست همانند لیست پارامترهای متد. نوع‌های قابل قبول یا Valid پارامترها برای Indexerها عبارت‌اند از integer، enum و رشته‌ها. علاوه بر این، Indexerها می‌توانند overload‌شوند.

در لیست ۲-۱۱، ما برنامه قبلی را اصلاح کردیم تا بتواند Indexerهای overload شده‌ای که نوع‌های مختلفی می‌گیرند را بپذیرد.

لیست ۲-۱۱. Indexerهای overload شده: OverIndexer.cs

using System;

/// <summary>
///     شدهoverload های indexer پیاده‌سازی.
/// </summary>
class OvrIndexer
{
    private string[] myData;
    private int         arrSize;

    public OvrIndexer(int size)
    {
        arrSize = size;
        myData = new string[size];

        for (int i=0; i < size; i++)
        {
            myData[i] = "empty";
        }
    }

    public string this[int pos]
    {
        get
       {
            return myData[pos];
        }
        set
       {
            myData[pos] = value;
        }
    }

    public string this[string data]
    {
        get
       {
            int count = 0;

            for (int i=0; i < arrSize; i++)
            {
                if (myData[i] == data)
                {
                    count++;
                }
            }
            return count.ToString();
        }
        set
       {
            for (int i=0; i < arrSize; i++)
            {
                if (myData[i] == data)
                {
                    myData[i] = value;
                }
            }
        }
    }

    static void Main(string[] args)
    {
        int size = 10;
        OvrIndexer myInd = new OvrIndexer(size);

        myInd[9] = "Some Value";
        myInd[3] = "Another Value";
        myInd[5] = "Any Value";

        myInd["empty"] = "no value";

        Console.WriteLine("\nIndexer Output\n");

        for (int i=0; i < size; i++)
        {
            Console.WriteLine("myInd[{0}]: {1}", i, myInd[i]);
        }

        Console.WriteLine("\nNumber of \"no value\" entries: {0}", myInd["no value"]);
    }
}

لیست ۲-۱۱ چگونگی overload کردن Indexerها را نشان می‌دهد. Indexer اول که دارای پارامتر int به نام pos است، درست همانند Indexer لیست ۱-۱۱ است، اما یک Indexer جدید وجود دارد که یک پارامتر از نوع رشته می‌گیرد.

Get accessor در این Indexer جدید، یک نماینده با نوع رشته از تعداد آیتم‌هایی که با مقدار پارامتر Data مطابقت دارند را بازمی‌گرداند. Set accessor همه ورودی‌های درون آرایه (ورودی‌هایی که با مقدار پارامتر data که در Indexer مشخص شده است مطابقت دارند) را تغییر می‌دهد.

رفتار ایندکسر overload شده که پارامتر از نوع رشته می‌گیرد، در متد ()Main از لیست ۲-۱۱ نشان داده شده است. این ایندکسر، set accessor را فراخوانی می‌کند، که این Accessor مقدار “no value” را به همه اعضای کلاس myInd که دارای مقدار “empty” باشند، اختصاص می‌دهد. Set accessor از این خط دستور استفاده می‌کند:

”myInd[“empty”] = “no value

بعد از اینکه همه ورودی‌های کلاس myInd چاپ شدند، یک ورودی نهایی در کنسول چاپ می‌شود که نشان‌دهنده تعداد ورودی‌های دارای رشته “no value” است. این خروجی به خاطر فراخوانی Get accessor توسط این خط کد انجام می‌شود:

[”myInd[“no value

خروجی برنامه به شرح زیر است:

Indexer Output

myInd[0]: no value
myInd[1]: no value
myInd[2]: no value
myInd[3]: Another Value
myInd[4]: no value
myInd[5]: Any Value
myInd[6]: no value
myInd[7]: no value
myInd[8]: no value
myInd[9]: Some Value

Number of "no value" entries: 7

دلیل اینکه هر دو Indexerهای لیست ۲-۱۱ می‌توانند کنار یکدیگر در یک کلاس مشابه قرار بگیرند، این است که آن‌ها دارای امضاهای متفاوت هستند. امضای Indexerتوسط تعداد و نوع پارامترها در لیست پارامتر Indexer مشخص می‌شود.

کلاس به قدری هوشمند است که می‌تواند تشخیص دهد کدام Indexer فراخوانی شده است، و این کار را بر اساس تعداد و نوع آرگومان‌ها در فراخوانی Indexer انجام می‌دهد. یک Indexer دارای چندین پارامتر را می‌توان به شکل زیر پیاده‌سازی کرد:

public object this[int param1, ..., int paramN]
    {
        get

       {
            // چند داده از کلاس را پردازش کرده و بازمی‌گرداند
        }
        set

       {
            // چند داده از کلاس را پردازش کرده و بازمی‌گرداند
        }
    }

خلاصه

حالا می‌دانید که Indexerها چه کاری انجام می‌دهند و چگونه مورد استفاده قرار می‌گیرند. می‌توانید برای دسترسی به اعضای کلاس درست همانند یک آرایه، از Indexer استفاده کنید. Indexerهای overload شده و چند پارامتری نیز توضیح داده شدند.

منبع: C#-Station

جلسه بعد                                                                جلسه قبل

 مطالب مرتبط

 مقدمه ای بر زبان برنامه نویسی #C و پلتفرم NET Framework.
7 دلیل منطقی برای آموختن #C
 طبقه بندی زبان های برنامه نویسی
به دست آوردن Exceptionها در #C و یافتن همه خطاها
 LINQ(زبان جستجوی یکپارچه)
برنامه نویسی شیءگرا چیست؟

از آخرین دوره های آموزشی و تخفیف ها مطلع شوید

با تکمیل فرم زیر ، از اخبار و اطلاعات به روز برنامه نویسی و تکنولوژی عقب نمانید

آخرین مطالب

آموزش جامع SQL Server (جلسه ۱۲)
آموزش جامع SQL Server (جلسه ۱۲)

دستور UPDATE در SQL Server برای تغییر داده‌های موجود در یک جدول، از دستور UPDATE به شکل زیر استفاده ...

آموزش جامع SQL Server (جلسه ۱۵)
آموزش جامع SQL Server (جلسه ۱۵)

دستور DROP TABLE در SQL Server گاهی، لازم است یک جدول که دیگر استفاده‌ای ندارد را حذف کنید. برای ...

آموزش جامع SQL Server (جلسه ۳۵: Window Functionها – بخش ۲)
آموزش جامع SQL Server (جلسه ۳۵: Window Functionها – بخش ۲)

بخش اول از آخرین مبحث دوره جامع آموزش SQL Server در جلسه قبلی بررسی شد. این مبحث که ...

آخرین دیدگاه ها

دیدگاه خود را درباره این پست بنویسید

فرم ارسال نظرات