اندازهی قلم متن
تخمین مدت زمان مطالعهی مطلب:
چهار دقیقه
در مطلب «C# 7 - Tuple return types and deconstruction» با نوعهای جدید بازگشتی Tuple در C# 7.0 آشنا شدیم. در C# 7.1 تشخیص نام اعضای Tuple تعریف شده بهبود یافته و از این لحاظ شبیه به anonymous types شدهاست. مفهوم «Name Inference» یا «حدس زدن نامها» را با یک مثال بهتر میتوان توضیح داد.
در C# 7.0 مفهوم «Name Inference» پیاده سازی نشدهاست. به همین جهت کامپایلر قادر نیست نام اعضای Tuple تعریف شدهی فوق را حدس بزند و برای دسترسی به آنها باید تنها از Item1 و Item2 مانند قبل استفاده کرد. البته اگر برای اعضای Tuple نام تعریف کنیم (قسمت «مفهوم Tuple Literals»)، آنگاه میتوان Item1 و Item2 را با نامهای این اعضاء جایگزین کرد:
بنابراین ذکر نام صریح اعضای Tuple در سیشارپ 7 الزامی است؛ در غیراینصورت باید با همان نامهای عمومی Item1 و Item2 جهت دسترسی به این اعضاء، کار کرد.
این وضعیت در C# 7.1 بهبود یافتهاست و اکنون کامپایلر در صورت عدم ذکر صریح نام اعضای Tuple، قادر است این نامها را دقیقا بر اساس نام متغیرها، همانند قابلیتی که در مورد anonymous types وجود دارد، تعیین کند و حدس بزند:
این مثال، شبیه به اولین مثالی است که در مورد C# 7.0 ذکر شد. اما در C# 7.1 نیازی به ذکر Item1 و Item2 جهت دسترسی به اعضای Tuple تعریف شده نیست (هرچند هنوز هم مجاز است) و کامپایلر نام این اعضاء را از نام متغیرهای متناظر با آنها حدس میزند.
مثالهایی از حدس زدن نامهای اعضای Tuple در C# 7.1
مثال اول همان حدس زدن نامهای اعضای Tuple بر اساس نام متغیرهای محلی متناظر با آنها است.
مثال دوم بر اساس نام خواص یک شیء است که توسط یک نوع Tuple بازگشت داده میشود:
در اینجا عملگر .? نیز پشتیبانی میشود:
مثال سوم همان مثال دوم است که در یک عبارت LINQ بکار رفتهاست:
در اینجا نوع خروجی عبارت LINQ نوشته شده، لیستی از Tupleها است. در Tuple خروجی آن، نام دو عضو اول، از نام خواص متناظر با آنها حدس زده میشود. نام عنصر سوم به صورت صریح مشخص شدهاست.
نکته 1: حدس زدن نامها در مورد مقادیر خروجی متدها رخ نمیدهد.
در مثال ذیل نمیتوان به personTuple.FirstName بر اساس نام متد ذکر شده دسترسی یافت و تنها میتوان از Item1 در مورد آن استفاده کرد؛ اما در مورد متغیر محلی age میتوان:
نکته 2: اگر نام اعضای Tuple یکی باشند، عملیات حدس زدن نامها رخ نمیدهد.
در این مثال چون Tuple تشکیل شده دارای نامهای یکسان Name است، امکان حدس زدن نامها میسر نیست و در اینجا نیز باید از طریق Item1 و ... به اعضای Tuple دسترسی یافت (و یا میتوان به هر عضو Tuple یک نام منحصربفرد را انتساب داد).
string name = "User 1"; int age = 20; var personTuple = (name, age); Console.WriteLine(personTuple.Item1); // User 1 Console.WriteLine(personTuple.Item2); // 20
string name = "User 1"; int age = 20; var personTuple = (name: name, age:age); Console.WriteLine(personTuple.name); // User 1 Console.WriteLine(personTuple.age); // 20
این وضعیت در C# 7.1 بهبود یافتهاست و اکنون کامپایلر در صورت عدم ذکر صریح نام اعضای Tuple، قادر است این نامها را دقیقا بر اساس نام متغیرها، همانند قابلیتی که در مورد anonymous types وجود دارد، تعیین کند و حدس بزند:
string name = "User 1"; int age = 20; var personTuple = (name, age); Console.WriteLine(personTuple.name); // User 1 Console.WriteLine(personTuple.age); // 20
مثالهایی از حدس زدن نامهای اعضای Tuple در C# 7.1
مثال اول همان حدس زدن نامهای اعضای Tuple بر اساس نام متغیرهای محلی متناظر با آنها است.
مثال دوم بر اساس نام خواص یک شیء است که توسط یک نوع Tuple بازگشت داده میشود:
var p = new Person { Name = "User 1", Age = 20 }; var personTuple = (p.Name, p.Age); Console.WriteLine(personTuple.Name); Console.WriteLine(personTuple.Age);
در اینجا عملگر .? نیز پشتیبانی میشود:
Person p = null; var personTuple = (p?.Name, p?.Age); Console.WriteLine(personTuple.Name); // null Console.WriteLine(personTuple.Age); // null
مثال سوم همان مثال دوم است که در یک عبارت LINQ بکار رفتهاست:
var people = new List<Person> { new Person {Name = "User 1", Age = 42}, new Person {Name = "User 2", Age = 18}, new Person {Name = "User 3", Age = 21} }; var tuples = people .Select(person => ( person.Name, person.Age, NameAndAge: $"{person.Name} is {person.Age}" ) ); var name = tuples.First().Name; var age = tuples.First().Age; var nameAndAge = tuples.First().NameAndAge;
نکته 1: حدس زدن نامها در مورد مقادیر خروجی متدها رخ نمیدهد.
در مثال ذیل نمیتوان به personTuple.FirstName بر اساس نام متد ذکر شده دسترسی یافت و تنها میتوان از Item1 در مورد آن استفاده کرد؛ اما در مورد متغیر محلی age میتوان:
int age = 42; var personTuple = (FirstName(), age); Console.WriteLine(personTuple.Item1); Console.WriteLine(personTuple.age);
نکته 2: اگر نام اعضای Tuple یکی باشند، عملیات حدس زدن نامها رخ نمیدهد.
var p1 = new Person { Name = "User 1", Age = 20 }; var p2 = new Person { Name = "User 2", Age = 22 }; var personTuple = (p1.Name, p2.Name); Console.WriteLine(personTuple.Item1); // User 1 Console.WriteLine(personTuple.Item2); // User 2