اندازهی قلم متن
تخمین مدت زمان مطالعهی مطلب:
شش دقیقه
هرچند کار کردن با کلاسها و اینترفیسهای strongly typed سادهتر است، اما گاهی از اوقات نیاز است تا با نوع object کار کرد. به علاوه حتی در حین کار کردن با کلاسها و اینترفیسها هم نیاز است تا نوع خاصی از کلاسهای مشتق شده را جهت فراخوانی متدی ویژه، بررسی کرد. به همین جهت مفهوم «pattern matching» به C# 7 اضافه شدهاست تا بتوان با سلسله مراتب اشیاء، سادهتر کار کرد. برای این منظور اپراتور is و عبارت switch، با الگوهای const ،var و type بهبود و تکامل بخشیده شدهاند.
استفاده از اپراتور is به همراه pattern matching
اپراتور is از اولین نگارش #C مهیا بودهاست و هدف آن بررسی تطابق شیءایی خاص، با نوعی مفروض است. برای مثال آیا این نوع مورد بررسی، اینترفیس خاصی را پیاده سازی میکند و یا اینکه آیا از کلاسی خاص مشتق شدهاست یا خیر؟ حاصل این بررسی هم true یا false است.
با بهبودهای حاصل شدهی در C# 7، اکنون میتوان از اپراتور is جهت بررسی الگوها نیز استفاده کرد.
الگوی const
در مثال ذیل، آرایهای از اشیاء، شامل یک نال، یک عدد و دو شیء کاربر، تعریف شدهاند:
اولین الگوی مهیای در C# 7، با نام «const pattern» شناخته میشود که نمونهای از آنرا در بدنهی حلقهی فوق مشاهده میکنید.
در C# 7 میتوان اپراتور is را بر روی یک عدد ثابت مانند 42 و یا یک null بکار گرفت. پیش از C# 7 برای بررسی نال بودن یک شیء، تنها از پراتور == میشد استفاده کرد.
الگوی Type
دومین الگوی مهیای در C# 7، «الگوی نوع» نام دارد و هدف آن بررسی تطابق یک شیء، با شیءایی دیگر است. مهمترین تفاوت آن با نگارشهای پیشین سی شارپ این است که اگر اکنون تطابقی تشخیص داده شود، شیء، به متغیر جدید تعریف شده، انتساب داده میشود:
همانطور که ملاحظه میکنید اینبار میتوان پس از اپراتور is، یک متغیر جدید را هم تعریف کرد و در صورت تطابق، این متغیر به صورت خودکار مقدار دهی میگردد. به علاوه در اینجا امکان ترکیب شرطها نیز پس از is، مانند سومین if نوشته شده، میسر است.
و یا اکنون قطعه کد قدیمی ذیل را
میتوان با pattern matching و استفاده از «الگوی نوع»، به نحو ذیل خلاصه کرد:
الگوی Var
سومین الگوی مهیای در C# 7، الگوی var نام دارد و در این حالت میتوان بجای ذکر صریح نوع تطابق داده شده، از var استفاده کرد.
بدیهی است این الگو همواره با موفقیت روبرو میشود؛ چون var به همان نوع شیء مفروض اشاره میکند:
مهمترین مزیت آن این است که متغیر تعریف شدهی پس از var دقیقا دارای همان مقدار و نوع اصلی شیء است و پس از فراخوانی GetType میتوان به خواص آن دسترسی یافت؛ مانند خاصیت Name ذکر شدهی در مثال فوق.
در این حالت اگر item دقیقا null باشد، برای بررسی آن میتوان از null conditional operator معرفی شدهی در C# 6 استفاده کرد.
استفاده از عبارت switch به همراه pattern matching
در C# 7، عبارت switch نیز تکامل یافتهاست. در اینجا الگوهای const ،var و type را نیز میتوان پس از ذکر case بکار گرفت:
الگوهایی را که در اینجا مشاهده میکنید دقیقا همانهایی هستند که پیشتر بررسی کردیم. الگوی const برای بررسی نال و یک عدد. الگوی type برای بررسی تطابق با یک شیء خاص و سپس استفادهی از آن شیء و الگوی var برای دسترسی به نام نوع مفروض.
تنها نکتهی جدید در اینجا، استفاده از واژهی کلیدی when است برای ترکیب شرطها (case User p when p.Name.StartsWith). بنابراین در C# 7 امکان نوشتن case null میسر است؛ به همراه نوشتن شرطها توسط when، در حین تعاریف caseها. به علاوه اینبار عبارت switch محدود به نوعهای پایه مانند اعداد، رشتهها و enums نیست و در اینجا میتوان یک شیء را نیز مشخص کرد.
شبیه سازی switch موجود در ویژوال بیسیک در C# 7
ویژوال بیسیک از نگارشهای ابتدایی آن دارای caseهای پیشرفتهتری است نسبت به #C. برای نمونه در اینجا امکان تعریف تعدادی عدد، استفاده از To و استفادهی از =< را هم مشاهده میکنید:
اکنون در C# 7 میتوان یک چنین توانمندی را با pattern matching هم پیاده سازی کرد:
در این مثال یکی از کاربردهای عملی الگوی var را مشاهده میکنید؛ یا همان دسترسی به مقدار و نوع وارد شده و سپس اعمال شرط بر روی آن.
همانطور که مشاهده میکنید، در قسمت when نیز میتوان توسط && و || نیز شرطها را ترکیب کرد و یا متدی را با خروجی bool (مانند Contains) بر روی مقدار دریافتی اعمال کرد.
استفاده از اپراتور is به همراه pattern matching
اپراتور is از اولین نگارش #C مهیا بودهاست و هدف آن بررسی تطابق شیءایی خاص، با نوعی مفروض است. برای مثال آیا این نوع مورد بررسی، اینترفیس خاصی را پیاده سازی میکند و یا اینکه آیا از کلاسی خاص مشتق شدهاست یا خیر؟ حاصل این بررسی هم true یا false است.
با بهبودهای حاصل شدهی در C# 7، اکنون میتوان از اپراتور is جهت بررسی الگوها نیز استفاده کرد.
الگوی const
در مثال ذیل، آرایهای از اشیاء، شامل یک نال، یک عدد و دو شیء کاربر، تعریف شدهاند:
public class User { public User(string name) { Name = name; } public string Name { get; } } object[] data = { null, 42, new User("User 1"), new User("User 2") }; foreach (var item in data) { if (item is null) Console.WriteLine("it's a const pattern"); if (item is 42) Console.WriteLine("it's 42"); }
در C# 7 میتوان اپراتور is را بر روی یک عدد ثابت مانند 42 و یا یک null بکار گرفت. پیش از C# 7 برای بررسی نال بودن یک شیء، تنها از پراتور == میشد استفاده کرد.
الگوی Type
دومین الگوی مهیای در C# 7، «الگوی نوع» نام دارد و هدف آن بررسی تطابق یک شیء، با شیءایی دیگر است. مهمترین تفاوت آن با نگارشهای پیشین سی شارپ این است که اگر اکنون تطابقی تشخیص داده شود، شیء، به متغیر جدید تعریف شده، انتساب داده میشود:
object[] data = { null, 42, new User("User 1"), new User("User 2") }; foreach (var item in data) { if (item is int i) Console.WriteLine($"it's a type pattern with an int and the value {i}"); if (item is User p) Console.WriteLine($"it's a person: {p.Name}"); if (item is User p2 && p2.Name.StartsWith("U")) { Console.WriteLine($"it's a person starting with U {p2.Name}"); } }
و یا اکنون قطعه کد قدیمی ذیل را
object obj1 = "Hello, World!"; var str1 = obj1 as string; if (str1 != null) { Console.WriteLine(str1); }
object obj2 = "Hello, World!"; if (obj2 is string str2) { Console.WriteLine(str2); }
الگوی Var
سومین الگوی مهیای در C# 7، الگوی var نام دارد و در این حالت میتوان بجای ذکر صریح نوع تطابق داده شده، از var استفاده کرد.
بدیهی است این الگو همواره با موفقیت روبرو میشود؛ چون var به همان نوع شیء مفروض اشاره میکند:
object[] data = { null, 42, new User("User 1"), new User("User 2") }; foreach (var item in data) { if (item is var x) Console.WriteLine($"it's a var pattern with the type {x?.GetType()?.Name}"); }
در این حالت اگر item دقیقا null باشد، برای بررسی آن میتوان از null conditional operator معرفی شدهی در C# 6 استفاده کرد.
استفاده از عبارت switch به همراه pattern matching
در C# 7، عبارت switch نیز تکامل یافتهاست. در اینجا الگوهای const ،var و type را نیز میتوان پس از ذکر case بکار گرفت:
public static void SwitchPattern(object o) { switch (o) { case null: Console.WriteLine("it's a constant pattern"); break; case int i: Console.WriteLine("it's an int"); break; case User p when p.Name.StartsWith("U"): Console.WriteLine($"a U person {p.Name}"); break; case User p: Console.WriteLine($"any other person {p.Name}"); break; case var x: Console.WriteLine($"it's a var pattern with the type {x?.GetType().Name} "); break; default: break; } }
تنها نکتهی جدید در اینجا، استفاده از واژهی کلیدی when است برای ترکیب شرطها (case User p when p.Name.StartsWith). بنابراین در C# 7 امکان نوشتن case null میسر است؛ به همراه نوشتن شرطها توسط when، در حین تعاریف caseها. به علاوه اینبار عبارت switch محدود به نوعهای پایه مانند اعداد، رشتهها و enums نیست و در اینجا میتوان یک شیء را نیز مشخص کرد.
شبیه سازی switch موجود در ویژوال بیسیک در C# 7
ویژوال بیسیک از نگارشهای ابتدایی آن دارای caseهای پیشرفتهتری است نسبت به #C. برای نمونه در اینجا امکان تعریف تعدادی عدد، استفاده از To و استفادهی از =< را هم مشاهده میکنید:
Select Case age Case 50 ageBlock = "the big five-oh" Case 80, 81, 82, 83, 84, 85, 86, 87, 88, 89 ageBlock = "octogenarian" Case 90 To 99 ageBlock = "nonagenarian" Case Is >= 100 ageBlock = "centenarian" Case Else ageBlock = "just old" End Select
اکنون در C# 7 میتوان یک چنین توانمندی را با pattern matching هم پیاده سازی کرد:
string ageBlock; var age = 40; switch (age) { case 50: ageBlock = "the big five-oh"; break; case var testAge when (new List<int> { 80, 81, 82, 83, 84, 85, 86, 87, 88, 89 }).Contains(testAge): ageBlock = "octogenarian"; break; case var testAge when ((testAge >= 90) && (testAge <= 99)): ageBlock = "nonagenarian"; break; case var testAge when (testAge >= 100): ageBlock = "centenarian"; break; default: ageBlock = "just old"; break; }
همانطور که مشاهده میکنید، در قسمت when نیز میتوان توسط && و || نیز شرطها را ترکیب کرد و یا متدی را با خروجی bool (مانند Contains) بر روی مقدار دریافتی اعمال کرد.