شنبه ۶ خرداد ۱۳۹۶
 
 
 
کلمه عبور خود را فراموش کرده اید؟
 

 
 
 سیر تکاملی Delegate ها - قسمت چهارم، Func and Action
.NET C#
تاریخ ثبت:  ۹۰/۹/۶
تعداد نمایش:  ۷۸۲۲
  نویسنده: مجید شهاب فر
 
   ۱۶  نفر تا این لحظه به این مقاله امتیاز داده اند.
 
   Bookmark and Share

به جاي تعريف يك delegate جديد با هر نوع برگشتي و پارامترهاي مختلف مي توان از delegate هاي Action<T> و Func<T> استفاده نمود. در اين مقاله به معرفي و نحوه استفاده از اين دو نوع delegate مي پردازيم.

در سري مقاله هاي قبلي موارد زير معرفي و بررسي شدند. اگر هنوز آنها را مطالعه نكرديد پيشنهاد مي شود نخست به مرور سه قسمت قبلي مقاله بپردازيد.

در NET 3.5. پنج نوع عمومي Func delegate وجود دارد. Func چيز خاصي ندارد و تنها در برگيرنده نوع هاي عمومي از پيش تعريف شده است كه مي توانند وضعيت هاي مختلفي را اداره كنند. delegate هاي تعريف شده توسط Func مي توانند تا چهار پارامتر از انواع مختلف را داشته باشند و علاوه بر اين چهار پارامتر يك پارامتر آخر هم براي مشخص كردن نوع برگشتي delegate به كار مي رود. نحوه نوشتن Func delegate ها در NET 3.5. بصورت زير مي باشد.

TResult Func<TResult>()
TResult Func<T,TResult>(T arg)
TResult Func<T1,T2,TResult>(T1 arg1, T2 arg2)
TResult Func<T1,T2,T3,TResult>(T1 arg1, T2 arg2, T3 arg3)
TResult Func<T1,T2,T3,T4,TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4)

بعنوان مثال

Func<string, double, int>

همانند delegate زير مي باشد:

public delegate int SomeDelegate(string arg1, double arg2)

شايد شما هم مثل بنده به محدوديت تعداد چهار پارامتر برخورد كرده باشيد مخصوصا" وقتي كه برنامه شما مبتني بر LINQ باشد. اين محدوديت در NET 4.0. برطرف شد و تعداد پارامترها به ۱۶ تا افزايش يافت.

 Delegate عمومي Action<T> عملكردي كاملا" مشابه با Func<T> دارد و تنها وجه تمايز آن با Func<T> اين است كه تنها وقتي كه delegate به تابعي بدون مقدار برگشتي (مقدار برگشتي void) ارجاع داده مي شود به كار مي رود. تابع تك پارامتري Action در NET 2.0. نيز وجود داشت ولي در NET. 3.5. كاملتر شد و در NET 4.0. نيز محدوديت تعداد پارامترهاي آن به ۱۶ تا افزايش يافت. 


يك مثال كاربردي:

مشاهده كرديد كه تعريف Func و Action بسيار ساده بود حال براي آنكه اين تعريف ملموس تر باشد آن را در قالب يك مثال كاربردي دنبال مي كنيم. در اينجا توجه شما را به مثالي برگرفته از كتاب Professional C# 4.0 and .NET 4.0 از انتشارات Wrox جلب مي كنم. در اين مثال كلاسي به نام BubbleSorter را مي نويسيم كه داراي يك تابع استاتيك به نام ()Sort خواهد بود كه بعنوان اولين پارامتر يك آرايه از نوع object را دريافت كرده و آن را بصورت صعودي مرتب مي كند. براي مرتب سازي از الگوريتم مرتب سازي حبابي استفاده شده است كه ساده ترين و مشهورترين روش مرتب سازي مي باشد. البته اين روش براي تعداد داده هاي كم به كار مي رود مثلا" كمتر از 100 تا اگر داده هاي شما زياد باشد الگوريتمهاي كارا تر ديگري وجود دارند. براي مرتب سازي اعداد صحيح، اين الگوريتم مطابف برنامه زير نوشته مي شود:

bool swapped = true;
do
{
  swapped = false;
  for (int i = 0; i < sortArray.Length — 1; i++)
  {
    if (sortArray[i] < sortArray[i+1]))   
    {
      int temp = sortArray[i];
      sortArray[i] = sortArray[i + 1];
      sortArray[i + 1] = temp;
      swapped = true;
    }
  }
} while (swapped);

اين كد براي مرتب سازي اعداد صحيح مي باشد اما تابعي مي خواهيم كه هر نوع آرايه اي را بتواند مرتب كند. پس بايد به سراغ استفاده از نوع عومي (generic type) برويم. يك تابع عومي ()Sort كه از generic type استفاده مي كند، مي تواند گزينه خوبي براي ما باشد.

به همراه تابع عمومي Sort<T>() كه يك پارامتر از نوع عمومي مثلا" T را دريافت مي كند، يك تابع مقايسه اي نيز مورد نياز است. اين تابع دو پارامتر از نوع T مي گيرد و نوع برگشتي آن bool خواهد بود. اين تابع مي تواند توسط delagate به فرم Func<T1, T2, TResult> ارجاع شود كه در آن T1 و T2 همنوع هستند كه در اين صورت delegate به فرم Func<T, T, bool> در خواهد آمد. با اين تفاصيل تعريف تابع ()Sort به شكل زير خواهد بود.

static public void Sort<T>(IList<T> sortArray, Func<T, T, bool> comparison)

اگر اين تابع را در كلاسي به نام BubbleSorter تعريف كنيم حاصل كار چنين خواهد شد:

class BubbleSorter
{
  static public void Sort<T>(IList<T> sortArray, Func<T, T, bool> comparison)
  {
    bool swapped = true;
    do
    {
      swapped = false;
      for (int i = 0; i < sortArray.Count — 1; i++)
      {
        if (comparison(sortArray[i+1], sortArray[i]))
        {
          T temp = sortArray[i];
          sortArray[i] = sortArray[i + 1];
          sortArray[i + 1] = temp;
          swapped = true;
        }
      }
    } while (swapped);
  }
}

حالا كافيست كه يك مجموعه نامرتب را به تابع Sort اين كلاس پاس كنيم تا مجموعه را طبق آن چيزي كه ما مي خواهيم مرتب كند. براي اين كار ابتدا يك كلاس تعريف مي كنيم كه شامل چند مشخصه باشد سپس آرايه اي از آن كلاس را براي مقصود مورد نظرمان ايجاد مي كنيم. بهترين مثال يك كلاس شامل مشخصات كارمندان يك شركت مي تواند باشد. چون تنها قصد تست كردن تابع Sort را داريم، كلاسمان را خيلي كامل تعريف نمي كنيم، دو مشخصه نام كارمند و ميزان حقوق دريافتي، كفايت مي كند.

class Employee
{
  public Employee(string name, decimal salary)
  {
    this.Name = name;
    this.Salary = salary;
  }
  
  public string Name { get; private set; }
  public decimal Salary { get; private set; }
  
  public override string ToString()
  {
    return string.Format("{0}, {1:C}", Name, Salary);
  }
  
  public static bool CompareSalary(Employee e1, Employee e2)
  {
    return e1.Salary < e2.Salary;
  }
}

توجه داشته باشيد كه براي همخواني با delegate تعريف شده <Func<T, T, bool تابع CompareSalary كه دو ارجاع از نوع Employee را گرفته و مقدار boolean برمي گرداند.
حال همه چيز آماده نوشتن كد جهت تست مرتب سازي مي باشد.

static void Main()
{
  Employee[] employees =
  {
    new Employee("Bugs Bunny", 20000),
    new Employee("Elmer Fudd", 10000),
    new Employee("Daffy Duck", 25000),
    new Employee("Wile Coyote", 1000000.38m),
    new Employee("Foghorn Leghorn", 23000),
    new Employee("RoadRunner", 50000)
  };
  
  BubbleSorter.Sort(employees, Employee.CompareSalary);
  
  foreach (var employee in employees)
  {
    Console.WriteLine(employee);
  }
}

اجراي اين كد موجب مرتب شدن Employee بر حسب حقوق مي شود.

  کیفیت مقاله ارائه شده از نظر شما   
برای دادن رتبه به این مقاله می بایست Login کرده باشید.
  درباره نویسنده
مجید شهاب فر
طراح، برنامه نویس و مدیر PersiaDevelopers.com
همه مقاله های نوشته شده توسط این کاربر (۱۸)
 
  پیام جدید
صفحه ۱ - پیامهای اصلی ۱ تا ۲ از مجموع ۲ پیام اصلی
اولین قبلی بعدی

 عنوان فرستنده تاریخ
 
تشکر و درخواست مقاله در مورد events Jahan Alem ۱۳۹۲/۵/۲۷
 
برنامه نویسی غیرهمزمان مریم مرادی ۱۳۹۰/۹/۲۰
پاسخ به: برنامه نویسی غیرهمزمان مجید شهاب فر ۱۳۹۰/۹/۲۳
اولین قبلی بعدی

Copyright © 2006 - 2016 All Rights Reserved.
Please direct your questions or comments to