متدهای توسعه یافته

همه متدها، وابسته به کلاسی هستند که در آن تعریف شده‌اند. اما ویژگی توسعه متدها (متدهای توسعه یافته) به شما اجازه می‌دهد که، متدی ایجاد کنید که علاوه بر کلاسی که در آن تعریف شده است، به کلاس‌های دیگر نیز وابسته باشد. می‌خواهیم نحوه استفاده از این ویژگی را به شما آموزش دهیم. به کد زیر توجه کنید. این کد شامل کلاسی به نام Class1 (خطوط 15-1) است که سه مقدار از نوع double (خط 3) را در خود ذخیره می‌کند، همچنین شامل یک سازنده (10-5) و یک متد به نام sum (14-11) است که جمع سه مقدار ذخیره شده را برگشت می‌دهد.

sealed class Class1
{
    private double D1, D2, D3;

    public Class1(double d1, double d2, double d3)
    { 
        D1 = d1; 
        D2 = d2; 
        D3 = d3; 
    }
    public double Sum() 
    { 
        return D1 + D2 + D3; 
    }
}

محدودیت این کلاس تا حدی خوب است، اما فرض کنید بخواهید از این کلاس بهتر استفاده کنید و متدی دیگری ایجاد کنید که میانگین سه مقدار ذکر شده را نیز برگرداند. با چیزهایی که در مورد کلاس‌ها یاد گرفته‌اید، چندین روش برای اجرای این کار (اضافه کردن متد) وجود دارد. اگر سورس اصلی کلاس را در اختیار داشته باشید و بتوانید آن را دستکاری کنید به راحتی می‌توانید متد جدیدی به آن اضافه نمایید. اگر به هر دلیلی نتوانید کلاس را دستکاری کنید، به عنوان مثال کلاس sealed باشد، مجبور می‌شوید که یک متد در کلاس دیگر تعریف کنید و آن را به صورت عمومی در دسترس اعضای کلاس قرار دهید. به عنوان مثال یک کلاس با نام ExtendClass1 با سطح دسترسی static می‌نویسیم که دارای متدی به نام Average و سطح دسترسی static است. به این نکته توجه کنید که متد Average() یک نمونه از کلاس Class1 را به عنوان پارامتر می‌گیرد.

static class ExtendClass1
{
    public static double Average(Class1 C1)
    {
        return C1.Sum() / 3;
    }
}

class Program
{
    static void Main()
    {
        Class1 C1 = new Class1(3, 4, 5);
        Console.WriteLine("Average: {0}", ExtendClass1.Average(C1));
    }
} 
4

با وجودیکه این راه حل کاملاً درست است، اما راه حل بهتر این است که متد را در نمونه کلاس خودش فراخوانی کنید، تا اینکه یک نمونه از کلاس دیگر ایجاد کرده و متد را فراخوانی کنید. در دو خط کد زیر تفاوت روشن می‌شود. در خط اول متد استاتیک به وسیله یک نمونه از کلاس دیگر و در خط دوم متد به وسیله یک شیء ایجاد شده از کلاس خودش فراخوانی شده است.

ExtendClass1.Average(C1); 

C1.Average();

توسعه متدها، به شما اجازه استفاده از روش دوم را می‌دهد، هر چند که روش اول روشی عادی برای فراخوانی می‌باشد. با اندکی تغییر در تعریف متد Average() از روش دوم استفاده کنید. تغییری که لازم است در متد بدهید اضافه کردن کلمه کلیدی this قبل از نام نوع در تعریف پارامترها می‌باشد، همانطور که در زیر نشان داده شده است. اضافه کردن کلمه کلیدی this به اولین پارامتر متد static کلاس static باعث تبدیل متد عادی کلاس ExtendClass1 به متد توسعه یافته کلاس Class1 می‌شود. حال می‌توان از هر دو حالت فراخوانی استفاده نمود.

static class ExtendClass1
{
     public static double Average(this Class1 C1)
     {
         .....
     }
}

نکات مهم درباره متد توسعه یافته در زیر ذکر شده است :

کد زیر همه برنامه را که شامل کلاس Class1 و متد توسعه یافته Average() تعریف شده در کلاس ExtendClass1 را نشان می‌دهد. به این نکته توجه کنید که که متد Average() دقیقاً طوری فراخوانی شده است که انگار یک عضو نمونه از کلاس Class1 است. کلاس‌های Class1 و ExtendClass1 هر دو با هم مانند یک کلاس با سه متد عمل می‌کنند.

using System;

namespace ExtensionMethods
{

    sealed class Class1
    {
        private double D1, D2, D3;

        public Class1(double d1, double d2, double d3)
        {
            D1 = d1;
            D2 = d2;
            D3 = d3;
        }
        public double Sum()
        {
            return D1 + D2 + D3;
        }
    }

    static class ExtendClass1
    {
       public static double Average(this Class1 C1)
       {                                           
            return C1.Sum() / 3;                   
       }                                           
    }

    class Program
    {
        static void Main()
        {
            Class1 C1 = new Class1(3, 4, 5);
            Console.WriteLine("Sum: {0}", C1.Sum());
            Console.WriteLine("Average: {0}", C1.Average());
        }
    }
}
Sum: 12
Average: 4