بررسی Tuple ها در C# 7

یکشنبه 10 اردیبهشت 1396

در C# 7 قابلیت های جدیدی اضافه شده که یکی از آنها Tuple ها می باشد که البته در ورژن های قبلی بود ولی در این ورژن تغییرات جالبی روی آنها انجام شده و استفاده از آنها را بسیار بهتر و کاراتر کرده است، در مقاله به آموزش tuple ها و مقایسه آنها با ورژن قدیمی آنها می پردازیم.

بررسی  Tuple ها  در C# 7

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

آیا از آنها استفاده کرده اید؟ آیا باید از آنها استفاده کنید؟ اگر از آنها استفاده کردید آیا آنها آنقدری مفید بودند که شما همیشه از آنها استفاده کنید؟ یا ترجیح می دهید روی کدهایی کار کنید که در آنها از تاپل ها استفاده نشده باشد و با دیدن تاپل ها سریعا از آنها دوری می کنید؟

سوال های زیادی در این زمینه هست که ما به چند تایی از آنها پاسخ خواهیم داد.

با اینکه C# 7 چند مدتی است که در حال استفاده است ولی با این حال هنوز از تاپل ها استفاده چندانی نشده است.

قبل از آنکه وارد بخش کدنویسی شویم باید ابتدا پکیج زیر را توسط NuGet نصب کنید. البته با توجه به ورژن ویژوال استودیو شما، ممکن است این پکیج در ویژوال استدیو شما وجود داشته باشد.

System.ValueTuple

کدنویسی

پیش از آنکه شروع به بررسی این قابلیت جدید در C# 7 کنیم، بررسی کنیم که تاپل ها در گذشته چگونه بودند.

    static void Main(string[] args)
    {
       Tuple<int, string> anOldTuple =
          new Tuple<int, string>(10, "count");
    }

در این قطعه کد، ما می بینیم که چگونه یک تاپل استاندارد ایجاد می شود. با یک int و یک string که مقدار آنها در اینجا  با مقدار دهی اولیه در همان نمونه سازی تعیین می شود.

وقتی که از این تاپل نمونه سازی انجام می شود، فیلد های آن فقط قابلیت خواندن دارن و فیلد های آن با نام هایی مثل item1 و item2 شناخته می شوند. در شکل زیر این نام گذاری ها نمایش داده شده است.

این مدل نام گذاری فیلد ها هیچگونه دیدی نسبت به نوع  و محتویات فیلد به ما نمی دهد که این یکی از نگرانی های اصلی ما در زمان استفاده از تاپل ها هست ولی در عوض استفاده از تاپل ها خیلی بهتر و به صرفه تر از ساخت یک کلاس یا  struct برای انتقال یک سری داده ساده است.

حالا به مقایسه تاپل هایی که قبلا دیدیم با تاپل های جدید می پردازیم

    static void Main(string[] args)
    {
       (int value, string name) newTuple = (10, "count");
    }

با نگاه به کد بالا اولین چیزی که متوجه می شویم این است که کدهای ایجاد یک تاپل بسیار خوانا تر و ساده تر است. البته باید ببینیم که چگونه می توان به فیلد های این تاپل دسترسی داشت.

حالا فیلد های ما دارای نام های معنی دار مشخصی هستند که با این نام گذاری فیلد ها، کار با آنها بسیار ساده تر خواهد بود. البته باید به این نکته توجه شود که اگر از کلمه کلیدی var استفاده شود این نام گذاری ها، ناپدید می شود.

    static void Main(string[] args)
    {
       var newTuple = (10, "count");
    }

حالا با توجه به آنچه در مورد تاپل ها در بالا توضیح داده شد، آیا شما علاقه مند به استفاده از تاپل های شده اید؟ به نظر شما در کجا می توان از این روش استفاده کرد؟

برای مواقعی که مقدار خروجی در یک متد private یا internal داشته باشیم، استفاده از این روش بسیار مناسب و ایده آل بنظر می رسد.

    class Program
    {
       static void Main(string[] args)
       {
          var result = GetData(new int[6] { 1, 3, 5, 6, 11, 20 });
          Console.WriteLine($"count : {result.count}");
          Console.WriteLine($"total : {result.total}");
          Console.WriteLine($"first value : {result.first}");
       }
     
       private static (int count, int total, int first)
          GetData(IEnumerable<int> values)
       {
          int count = values.Count();
          int total = values.Sum();
          int firstValue = values.First();
     
          return (count, total, firstValue);
       }
    }

با توجه به کد بالا، ما می توانیم از ساخت یک type که فقط مخصوص این متد باشد و صرفا در داخل کلاس استفاده می شود و فقط یکبار فراخوانی می شود، اجتناب کنیم. و در عین حال می توانیم از نام گذاری معنی دار فیلد ها استفاده کنیم که باعث خوانایی بیشتر کد می شود.

در پایین نتیجه نهایی کد بالا را مشاهده می کنید.

این روش برای مواقعی که خروجی چند مقداری داریم که قرار است از طریق Task<T> ارسال شود، بسیار مفید است. برای مثال کد زیر را ببینید.

    private static async Task<(int min, int max)>
       GetMinMax(IEnumerable<int> values)
    {
       await Task.Delay(1000);
       return (values.Min(), values.Max());
    }

به دلیل اینکه ما اکثرا از متد ها asynchronous برای کارهای مرتبط با UI استفاده میکنیم، در مواقعی که این متدها پارامتر خروجی نداشته باشند، استفاده از روش بالا بسیار خوب و مفید است.

آموزش سی شارپ

برنامه نویسان

نویسنده 3355 مقاله در برنامه نویسان
  • C#.net
  • 3k بازدید
  • 7 تشکر

کاربرانی که از نویسنده این مقاله تشکر کرده اند

در صورتی که در رابطه با این مقاله سوالی دارید، در تاپیک های انجمن مطرح کنید