عنوان:

‫آشنایی با مفهوم Indexer در C#.NET


نویسنده: علیرضا اسم‌رام
تاریخ: ۱۳۹۱/۰۴/۲۰ ۱۹:۵۶
آدرس: www.dntips.ir
زمانی که صحبت از Indexer می‌شود، بطور ناخوداگاه ذهنمان به سمت آرایه‌ها می‌رود. آرایه‌ها در واقع ساده‌ترین اشیاء ی هستند که مفهوم Index در آنها معنا دار است.
اگر با آرایه‌ها کار کرده باشید با عملگر [] در سی شارپ آشنایی دارید. یک Indexer در واقع نوع خاصی از خاصیت (property) است که در بدنه کلاس تعریف می‌شود و به ما امکان استفاده از عملگر [] را برای نمونه کلاس فراهم می‌کند.
همانطور که به شباهت Indexer و Property اشاره شد نحوه تعریف Indexer بصورت زیر می‌باشد:
public type this [type identifier]
{
     get{ ... }
     set{ ... }
}
در پیاده سازی Indexer به نکات زیر دقت کنید:
  • از کلمه کلیدی this برای نعریف Indexer استفاده می‌شود و یک Indexer نام ندارد.
  • از دستیاب get برای برگرداندن مقدار و از دستیاب set جهت مقدار دهی و انتساب استفاده می‌شود.
  • الزامی به پیاده سازی Indexer با مقادیر صحیح عددی نیست و شما می‌توانید Indexer ی با پارامترهایی از نوع string یا double داشته باشید.
  • Indexer‌ها قابلیت سربارگذاری (overloaded) دارند.
  • Indexer‌ها می‌توانند چندین پارامتری باشند مانند آرایه‌های دو بعدی که دو پارامتری هستند.
به مثالی جهت پیاده سازی کلاس ماتریس توجه کنید:
public class Matrix
{
    // فیلدها
    private int _row, _col;
    private readonly double[,] _values;

    // تعداد ردیف‌های ماتریس
    public int Row
    {
        get { return _row; }
        set
        {
            _row = value > 0 ? value : 3;
        }
    }

    // تعداد ستون‌های ماتریس
    public int Col
    {
        get { return _col; }
        set
        {
            _col = value > 0 ? value : 3;
        }
    }

    // نعریف یک ایندکسر
    public double this[int r, int c]
    {
        get { return Math.Round(_values[r, c], 3); }
        set { _values[r, c] = value; }
    }

    // سازنده 1
    public Matrix()
    {
        _values = new double[_row,_col];
    }

    // سازنده 2
    public Matrix(int row, int col)
    {
        _row = row;
        _col = col;
        _values = new double[_row,_col];
    }

}
نحوه استفاده از کلاس ایجاد شده:
public class UseMatrixIndexer
{
    // ایجاد نمونه از شیء ماتریس
    private readonly Matrix m = new Matrix(5, 5);

    private double item;

    public UseMatrixIndexer()
    {
        // دسترسی به عنصر واقع در ردیف چهار و ستون سه
        item = m[4, 3];
    }
}

نظرات

  • وحید نصیری در ۱۳۹۱/۰۴/۲۰ ۲۱:۶
    ممنون. Indexer مطلب جالبی است؛ ولی یک مورد کلا از زبان سی شارپ از قلم افتاده به نام indexed property
    در حالت عادی می‌شود بر روی یک وهله از کلاس، Index اعمال کرد. اگر نخواهیم روی کل وهله اعمال شود چطور؟ برای مثال فقط روی یک خاصیت خاص.
    پیاده سازی آن یک نکته کوچک دارد که به شرح زیر است:

    using System;
    
    namespace IndexedProperties
    {
        public class Data
        {
            private int[] _localArray;
            private ArrayIndexer _arrayIndexer;
    
            public Data()
            {
                _localArray = new int[10];
                for (int i = 0; i < 10; i++)
                    _localArray[i] = i + 1;
                _arrayIndexer = new ArrayIndexer(this);
            }
            
            public ArrayIndexer Number
            {
                get { return _arrayIndexer; }
            }       
    
            public class ArrayIndexer
            {
                private Data _arrayOwner;
    
                public ArrayIndexer(Data arrayOwner)
                {
                    _arrayOwner = arrayOwner;
                }
    
                public int this[int index]
                {
                    get { return _arrayOwner._localArray[index]; }
                }
    
                public int Length
                {
                    get { return _arrayOwner._localArray.Length; }
                }
            }
        }
    
    
        class Program
        {
            static void Main(string[] args)
            {
                var data = new Data();
                for (int i = 0; i < 10; i++)
                    Console.WriteLine(data.Number[i]);
            }
        }
    }
    در اینجا از کلاس‌های تودرتو برای پیاده سازی Indexed property استفاده شده است.
    به این ترتیب تعاریف آرایه مورد استفاده نیازی نیست مستقیما در معرض دید قرار گیرد و همچنین read-only هم تعریف شده است. به علاوه اینکه indexerها محدود به int نیستند و برای مثال می‌توان از string و غیره نیز استفاده کرد.
     
    • میثم هوشمند در ۱۳۹۱/۰۴/۲۱ ۰:۳۶
      از هر دو نفر خیلی خیلی ممنونم
      خب جناب نصیری خود این یک پست بود :) تشکر
      • مهمان در ۱۳۹۱/۰۴/۲۱ ۲۱:۲۴
        سلام .
        ممنون از این مطلب جالب و پر استفاده . اما من یه چیزی فهمیدم ، اونم اینکه چقدر چیز نمیدونم :)
        در پناه خدا موفق و پیروز باشید