آموزش switch پیشرفته در سی شارپ

Ratings
(0)

در فصل 4، دستور switch معرفی شد. در آنجا case هایی از دستور switch بر اساس مقدار یک متغیر خاص بررسی می شدند.   

کد زیر را به یاد بیاورید، که <testVar> یک متغیر است که مورد تست قرار می گیرد. که می تواند از نوع یک عدد صحیح(integer) یا رشته(string) یا یک بولین(boolean) باشد. بعنوان مثال اگر این متغیر یک عدد صحیح باشد، یک مقدار عددی دارد و case مورد نظر، یک مقدار خاص را بررسی خواهد کرد(1 و 2 و غیره) و آنگاه وقتی مورد تطابق قرار گرفت، کدهایی را اجرا می کند. 

switch (<testVar>)
{
  case <comparisonVal1>:
    <code to execute if <testVar> == <comparisonVal1> >
    break;
  case <comparisonVal2>:
    <code to execute if <testVar> == <comparisonVal2> >
    break;
...
  case <comparisonValN>:
    <code to execute if <testVar> == <comparisonValN> >
    break;
  default:
    <code to execute if <testVar> != comparisonVals>
    break;
}

در سی شارپ 7، این امکان امکان وجود دارد که پترن ها را در یک دستور switch بسته به نوع متغیر، مورد تطابق قرار دهیم. بعنوان مثال یک رشته یا آرایه ای از اعداد صحیح. آنگاه، چونکه نوع مورد نظر را می دانیم، می توانیم به متدها و پروپرتی های(properties) آن نوع دسترسی داشته باشیم. ساختار سوئیچ زیر را در نظر بگیرید:

switch (<testVar>)
{
  case int value:
    <code to execute if <testVar> is an int >
    break;
  case string s when s.Length == 0:
    <code to execute if <testVar> is a string with a length = 0 >
    break;
  ...
  case null:
    <code to execute if <testVar> == null >
    break;
  default:
    <code to execute if <testVar> != comparisonVals>
    break;
}

 مستقیماً پس از کلمه ی کلیدی case، نوع(type) متغیری قرار دارد که می خواهیم آن را بررسی کنیم(string یا int و غیره).  مقدار آن نوع، زمانی که تطابقی در case وجود داشته باشد، در متغیر اعلام شده قرار می‌گیرد. بعنوان مثال، اگر <testVar> یک عدد صحیح(integer) باشد، مقدار این عدد صحیح، در متغیری به نام value قرار می گیرد.  

 بعد، به کلمه ی کلیدی when توجه کنید که در سی شارپ 6 معرفی شده است و به آن بعنوان یک فیلتر کننده ی عبارت رجوع می شود و در سی شارپ 7 به عبارت درون case از دستور switch اعمال می شود(در فصل 7 بیشتر در مورد آن بحث می کنیم). کلمه ی کلیدی when به ما امکان می دهد تا شرط های ضروری اضافه ای را برای اجرای کدی که در داخل دستور case وجود دارد اضافه کنیم. در خودتان امتحان کنید زیر، آنچه که توضیح داده ایم را با جزئیات بیشتری بعلاوه ی مفاهیم اضافه تری پوشش می دهیم:


 خودتان امتحان کنید: برای دانلود فایل Ch05Ex05\Program.cs، اینجا کلیک کنید.

1. یک اپلیکیشن کنسول جدید به نام Ch05Ex05 در آدرس زیر ایجاد کنید: 

C:\BeginningCSharp7\Chapter05

2. در فایل Program.cs کد زیر را اضافه کنید:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Console;

namespace Ch05Ex05
{
    class Program
    {
        static void Main(string[] args)
        {            
            string[] friendNames = { "Todd Anthony", "Kevin Holton",
                                     "Shane Laigle", null, "" };
            foreach (var friendName in friendNames)
            {
                switch (friendName)
                {
                    case string t when t.StartsWith("T"):
                        WriteLine("This friends name starts with a 'T': " +
                            $"{friendName} and is {t.Length - 1} letters long ");
                        break;
                    case string e when e.Length == 0:
                        WriteLine("There is a string in the array with no value");
                        break;
                    case null:
                        WriteLine("There was a 'null' value in the array");
                        break;
                    case var x:
                        WriteLine("This is the var pattern of type: " +
                            $"{x.GetType().Name}");
                        break;
                    default:
                        break;
                }
            }

            WriteLine();
            WriteLine("=================================================");
            WriteLine();

            int sum = 0, total = 0, counter = 0, intValue = 0;
            int?[] myIntArray = new int?[7] { 5, intValue, 9, 10, null, 2, 99 };
            foreach (var integer in myIntArray)
            {
                switch (integer)
                {
                    case 0:
                        WriteLine($"Integer number '{total}' has a default value of 0");
                        total++;
                        break;
                    case int value:
                        sum += value;
                        WriteLine($"Integer number '{total}' has a value of {value}");
                        total++;
                        counter++;
                        break;
                    case null:
                        WriteLine($"Integer number '{total}' is null");
                        total++;
                        break;
                    default:
                        break;
                }
            }
            WriteLine($"{total} total integers, {counter} integers with a " +
                      $"value other than 0 or null have a sum value of {sum}");
            ReadLine();
        }
    }
}

3. پس از اینکه مطمئن شدید که عبارت  static System.Console را به کد خود اضافه کردید، کدها را اجرا کنید. نتیجه در تصویر 5.10 نشان داده شده است:

(تصویر 5.10)

نتیجه اجرای کد در سی شارپ

 


توضیح کدهای بالا

در این خودتان امتحان کنید، دو حلقه ی foreach وجود دارند: یکی از آنها روی آرایه ی string[] و دیگری روی آرایه ی int[] کار می کند. آن حلقه ی foreach که آرایه ی string[] را پردازش می کند، عمداً شامل مقدار null و ورودی بدون مقدار است تا مفهوم تطبیق الگو(Pattern Matching) را با جزئیات بیشتری شرح دهد:

string[] friendNames = { "Todd Anthony", "Kevin Holton", "Shane Laigle", null, "" };

 در داخل این عبارت switch، چهار case بررسی می شوند:

case string t when t.StartsWith("T")

واضح ترین تفاوتی که وقتی دو عبارت switch بدون الگو(non-Pattern) را با این مثال مقایسه می کنیم، این است که سوئیچ زدن روی یک مقدار خاص مانند 1 یا 2 یا عبارت "Beginning C# Rocks" ، مستقیماً پس از case، یک تعریف از یک رشته(string) که آن را t نام گذاری کرده ایم ارائه شده است. 

وقتی که t تعریف شد، می توانیم از آن برای دسترسی به مقدار ذخیره شده در friendName دسترسی پیدا کنیم و متدها و پروپرتی ها(properties) از این نوع رشته در دسترس خواهند بود. توجه کنید که متد StartsWith() از طریق کلاس System.String در دسترسی خواهد بود و پس از عبارتِ فیلترِ when مورد استفاده قرار می گیرد. متد StartsWith() یک پارامتر می پذیرد و اگر مقدار رشته که در friendName قرار دارد، با این پارامتر آغاز شود(در این مثال، "T") آنگاه case مورد نظر مورد تطابق قرار می گیرد و کدهای این case اجرا می شوند. 

عبارت case بعدی به دنبال یک رشته ی خالی(empty) می گردد:

case string e when e.Length == 0

دوباره، اعلان string به نام e نام گذاری شده است و به ویژگی Length از کلاس System.String رجوع کرده است. اگر طول(length) برابر با 0 باشد، آنگاه کدهای آن case اجرا می شوند. قططع کد زیر، یک عبارت case است که بررسی می کند که آیا مقدار درون friendName برابر با null است یا خیر:

case null

 قطعه کد زیر مثالی از استفاده از اعلان var برای x جهت دریافت هر نوع متغیر دیگری است. ما می دانیم که تمام عناصر درون این آرایه رشته(string) هستند اما در برخی پیاده‌سازی‌های دیگر، این می‌تواند آرایه‌ای از اشیاء ناشناخته باشد. سپس، با استفاده از متد GetType() که به کلاس System.Object تعلق دارد، از طریق x می توانیم نوع آن را مشاهده کنیم. 

case var x

این عبارت یک نکته کلیدی را برای ویژگی تطبیق الگو(Pattern Matching) مطرح می کند؛  به این ترتیب که عبارت های case اکنون مهم محسوب می شوند.  

 


 اگر عبارت case var x را در بالای switch قرار داده بودید، 

Had you placed the case var x expression at the top of the switch,

 

تمام رشته یا هر چیزی که در string[] قرار دارد را می گرفت. 

it would catch
all the string or everything in the string[].

 

 اما نگران نباشید، زیرا اگر این کار را انجام دهید، کامپایلر شکایت می کند و به ما می گوید: این case از دستور switch قبلا توسط یک case قبلی به کار رفته است. 

 


به یاد داشته باشید که اکنون که این تطبیق الگو(Pattern Matching) را داریم، فیلترهای عبارت مورد نظر، نیاز دارند تا تا جای امکان دقیق باشند و باید در داخل دستور switch یکتا(unique) باشند. آرایه int[] نیز چند نکته دارد که باید به طور دقیق بررسی شوند.

int?[] myIntArray = new int?[7] { 5, intValue, 9, 10, null, 2, 99 };

اولاً توجه کنید که یک علامت سوال(?) درست پس از اعلان int وجود دارد. این علامت سوال به کامپایلر امکان می دهد تا بداند که آین آرایه ی  int[] بتواند حاوی آبجکت های null باشد. بدون این علامت، یک استثنا یا اعتراض کامپایل(compile exception) نمایش داده می شود. 

دوماً، رایج است که برای یک int، وقتی که مقداردهی اولیه می شود، یک مقدار پیش فرض 0 تنظیم کنیم. اگر یک عبارت switch case بنویسیم که در آن انتظار اعداد صحیح داشته باشیم، باید حالات خاص آن را بررسی کنیم و آن سناریو را به طور مناسب مدیریت کنیم. 

case 0

اگر بررسی برای 0 وجود نداشته باشد، آنگاه به case بعدی خواهیم رفت:

case int value:
  sum += value;

اگر مقدار 0 را به عنوان value به sum اضافه کنیم، منجر به تغییری در مقدار sum نمی شود؛ پس در اینجا، بدون عبارت case 0 انجام می شود. اگر کدها را بررسی کنید می بینید که تنها اعداد صحیح با یک مقداری غیر از 0 و null به sum و  counter اضافه می شوند.

در تمام تکرارها، مجموع به اندازه ۱ واحد افزایش می‌یابد. شما بدون کدنویسی نمی دانستید که آیا 0 یک مقدار حقیقی است یا یک مقداردهی اولیه است که به آرایه ی مورد نظر اضافه شده است. case 0 به ما فرصت می دهد تا کدی را اجرا کنیم تا آن را تایید کند. 

قطعه کد زیر، یک عبارت case را نشان می دهد که بررسی می کند که مقدار درون value برابر با null باشد:

case null

علاوه بر الگوی عبارت case در switch، در تطابق الگو(Pattern Matching) می توانیم از کلمه ی کلیدی is نیز استفاده کنیم. این کلمه ی کلیدی، تا فصل 11 معرفی نمی شود؛ در فصل 11، یاد می گیریم چگونه با استفاده از is تطابق الگو را انجام دهیم. 

 

  • بازدید: 68

نوشتن دیدگاه

لطفا نظرات خود را بیان کنید. به سوالات در سریع ترین زمان پاسخ داده خواهد شد.اما به نکات زیر توجه کنید:
1. سعی کنید نظرات شما مرتبط با مقاله ی مورد نظر باشد، در غیر این صورت پاسخ داده نخواهد شد.
2. سوالات خود را به صورت کوتاه بیان کنید و از پرسیدن چند سوال به طور همزمان خودداری کنید.
3. سوال خود را به طور واضح بیان کنید و از کلمات مبهم استفاده نکنید.

ارسال