Tuple چیست

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

using System;

namespace TupleDemo
{
    public class MethodArguments
    {
        public int ID { get; set; }
        public string Name { get; set; }
    }
    class Program
    {
        public static void Print(MethodArguments args)
        {
            Console.WriteLine("ID = " + args.ID.ToString());
            Console.WriteLine("Name =  " + args.Name);
        }
        public static void Main(string[] args)
        {
            MethodArguments arguments = new MethodArguments();
            arguments.ID = 20;
            arguments.Name = "John";

            Print(arguments);

            Console.ReadKey();
        }
    }
}

روش کلاسیک (بدون استفاده از Tuple) به این صورت است که باید ابتدا یک کلاس در برنامه تعریف کنید که دارای دو خاصیت باشد، سپس آرگومان ورودی متد را از نوع این کلاس تعریف می‌کنیم. حال یک شیء از کلاس ایجاد کرده و خاصیت‌های آن را مقداردهی می‌کنیم. سپس این شیء را به متد ارسال می‌کنیم. در متد نیز مقادیر را از خاصیت‌های استخراج می‌کنیم و آنها را نمایش می‌دهیم. این روش برای تعداد زیاد پارامترها نیز جوابگو است و به هر تعداد پارامتری که نیاز داشتید می‌توانید در کلاس، خاصیت ایجاد کنید و به شیوه مشابه آنها را مقداردهی و به متد مورد نظر ارسال کنید.
مشکلات این روش این است که شما برای هر متد باید یک کلاس جداگانه تعریف کنید که بسیار وقت گیر و کسل کننده است. Tuple این کار را به صورت خودکار برای شما انجام می‌دهد. زمانی که شما از Tuple استفاده می‌کنید، کامپایلر سی شارپ کلاس مورد نظر را برای شما در پشت صحنه ایجاد می‌کند. مثال بالا را این بار با Tuple پیاده سازی می‌کنیم :

using System;

namespace TupleDemo
{
    class Program
    {
        public static void Print(Tuple<int, string> args)
        {
            Console.WriteLine("ID = " + args.Item1.ToString());
            Console.WriteLine("Name =  " + args.Item2);
        }
        public static void Main(string[] args)
        {
            var arguments = new Tuple<int, string>(20, "John");
            Print(arguments);

            Console.ReadKey();
        }
    }
}

در مثال بالا دیگر نیازی به کلاس MethodArguments نداریم. ورودی متد را از نوع Tuple<int, string> تعریف می‌کنیم. در متد ()Main یک شیء به نام arguments از نوع Tuple<int, string> تعریف کرده‌ایم. اینطور در نظر بگیرید که با اینکار کامپایلر در پشت صحنه یک کلاس شبیه کلاس MethodArguments تعریف می‌کند که دارای دو خاصیت می‌باشد. نوع آنها به ترتیب int و string بوده و نام آنها به ترتیب Item1 و Item2 است. این نامگذاری به صورت خودکار انجام می‌شود یعنی اگر ما یک پارامتر دیگر مثلاً از نوع bool تعریف کنیم کامپایلر نام آنرا Item3 می‌گذارد. در ادامه این شیء را به متد ()Print ارسال می‌کنیم. دقت کنید که نوع پارامتر Print باید دقیقاً شبیه به نوع شیء ایجاد شده (در اینجا Tuple<int, string>) باشد. روش دیگر برای ایجاد Tuple استفاده از متد ()Create این کلاس می‌باشد. در این صورت اگر خط زیر را جایگزین خط بالا کنید، همان نتیجه حاصل می‌شود :

var arguments = Tuple.Create(20, "John");

به این نکته توجه کنید که خروجی متدها می‌تواند از نوع Tuple باشد :

using System;

namespace TupleDemo
{
    class Program
    {
        public static Tuple<string, string> GetPerson()
        {
            return new Tuple<string, string>("John", "Scith");
        }
        public static void Main(string[] args)
        {
            var person = GetPerson();

            Console.WriteLine(person.Item1 + " " + person.Item2);

            Console.ReadKey();
        }
    }
}

در مثال بالا یک متد به نام ()GetPerson با نوع خروجی Tuple<string, string> تعریف کرده‌ایم. در بدنه آن یک شیء از نوع Tuple<string, string> ایجاد کرده‌ایم و آنرا برگشت می‌دهیم. در متد ()Main خروجی متد را در متغیر person قرار داده و مقدار خاصیت‌های آنرا در خط بعدی نمایش می‌دهیم.