مطالب
C# 7 - Pattern matching and switch expressions
هرچند کار کردن با کلاس‌ها و اینترفیس‌های strongly typed ساده‌تر است، اما گاهی از اوقات نیاز است تا با نوع object کار کرد. به علاوه حتی در حین کار کردن با کلاس‌ها و اینترفیس‌ها هم نیاز است تا نوع خاصی از کلاس‌های مشتق شده را جهت فراخوانی متدی ویژه، بررسی کرد. به همین جهت مفهوم «pattern matching» به C# 7 اضافه شده‌است تا بتوان با سلسله مراتب اشیاء، ساده‌تر کار کرد. برای این منظور اپراتور is و عبارت switch، با الگوهای const ،var و type بهبود و تکامل بخشیده شده‌اند.


استفاده از اپراتور 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، با نام «const pattern» شناخته می‌شود که نمونه‌ای از آن‌را در بدنه‌ی حلقه‌ی فوق مشاهده می‌کنید.
در 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}");
    }
}
همانطور که ملاحظه می‌کنید اینبار می‌توان پس از اپراتور is، یک متغیر جدید را هم تعریف کرد و در صورت تطابق، این متغیر به صورت خودکار مقدار دهی می‌گردد. به علاوه در اینجا امکان ترکیب شرط‌ها نیز پس از is، مانند سومین if نوشته شده، میسر است.

و یا اکنون قطعه کد قدیمی ذیل را
object obj1 = "Hello, World!";
var str1 = obj1 as string;
if (str1 != null)
{
   Console.WriteLine(str1);
}
می‌توان با pattern matching و استفاده از «الگوی نوع»، به نحو ذیل خلاصه کرد:
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}");
}
مهم‌ترین مزیت آن این است که متغیر تعریف شده‌ی پس از var دقیقا دارای همان مقدار و نوع اصلی شیء است و پس از فراخوانی 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;
    }
}
الگوهایی را که در اینجا مشاهده می‌کنید دقیقا همان‌هایی هستند که پیشتر بررسی کردیم. الگوی 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 و استفاده‌ی از =< را هم مشاهده می‌کنید:
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;
}
در این مثال یکی از کاربردهای عملی الگوی var را مشاهده می‌کنید؛ یا همان دسترسی به مقدار و نوع وارد شده و سپس اعمال شرط بر روی آن.
همانطور که مشاهده می‌کنید، در قسمت when نیز می‌توان توسط && و || نیز شرط‌ها را ترکیب کرد و یا متدی را با خروجی bool (مانند Contains) بر روی مقدار دریافتی اعمال کرد.
اشتراک‌ها
0.Visual Studio 2017 15.9 منتشر شد

Summary of Notable New Features in 15.9

Top Issues Fixed in 15.9

0.Visual Studio 2017 15.9 منتشر شد
مطالب
معرفی Selector های CSS - قسمت 6
51- :first-child
تگی را انتخاب می‌کند که اولین فرزند والد خود باشد.
<style>
    div.container :first-child {
        color: red;
    }
</style>
<div class="container">
    <h1>Text 1</h1>
    <span>Text 2</span>
    <p>Text 3</p>
    <div>Text 4</div>
    <div>Text 5</div>
    <div>
        <h1>Text 6</h1>
        <span>Text 7</span>
        <p>Text 8</p>
        <p>
            <span>Text 9</span>
        </p>
        <div>Text 10</div>
        <p>Text 11</p>
    </div>
    <h1>Text 12</h1>
    <div>Text 13</div>
    <span>Text 14</span>
    <div>Text 15</div>
</div>
در مثال فوق Text 1، Text 6و Text 9 به رنگ قرمز نمایش می‌یابند.
پشتیبانی در مرورگرها:

 Selector نسخه CSS
 3.1 9.6  7.0 3.0  4.0 :first-child 2

52- :last-child
تگی را انتخاب می‌کند که آخرین فرزند والد خود باشد.
<style>
    div.container :last-child {
        color: red;
    }
</style>
<div class="container">
    <h1>Text 1</h1>
    <span>Text 2</span>
    <p>Text 3</p>
    <div>Text 4</div>
    <div>Text 5</div>
    <div>
        <h1>Text 6</h1>
        <span>Text 7</span>
        <p>Text 8</p>
        <p>
            <span>Text 9</span>
        </p>
        <div>Text 10</div>
        <p>Text 11</p>
    </div>
    <h1>Text 12</h1>
    <div>Text 13</div>
    <span>Text 14</span>
    <div>Text 15</div>
</div>
در مثال فوق Text 15، Text 11و Text 9 به رنگ قرمز نمایش می‌یابند. 
پشتیبانی در مرورگرها:

 Selector نسخه CSS
 3.2  9.6  9.0 3.5  4.0 :last-child  3

53- :only-child
تگی را انتخاب می‌کند که تنها فرزند والد خود باشد.
<style>
    div.container :only-child {
        color: red;
    }
</style>
<div class="container">
    <h1>Text 1</h1>
    <span>Text 2</span>
    <p>Text 3</p>
    <div>Text 4</div>
    <div>Text 5</div>
    <div>
        <h1>Text 6</h1>
        <span>Text 7</span>
        <p>Text 8</p>
        <p>
            <span>Text 9</span>
        </p>
        <div>Text 10</div>
        <p>Text 11</p>
    </div>
    <h1>Text 12</h1>
    <div>Text 13</div>
    <span>Text 14</span>
    <div>Text 15</div>
</div>
در مثال فوق Text 9 به رنگ قرمز نمایش می‌یابد.  
پشتیبانی در مرورگرها:

 Selector نسخه CSS
 3.2  9.6  9.0 3.5  4.0 :only-child  3

54- :nth-child(n)
تگی را انتخاب می‌کند که nامین فرزند والد خود باشد. به جای n می‌توان از مقادیر odd (فرزندان فرد)، even (فرزندان زوج) و an+b استفاده نمود.
<style>
    div.container :nth-child(2) {
        color: red;
    }
</style>
<div class="container">
    <h1>Text 1</h1>
    <span>Text 2</span>
    <p>Text 3</p>
    <div>Text 4</div>
    <div>Text 5</div>
    <div>
        <h1>Text 6</h1>
        <span>Text 7</span>
        <p>Text 8</p>
        <p>
            <span>Text 9</span>
        </p>
        <div>Text 10</div>
        <p>Text 11</p>
    </div>
    <h1>Text 12</h1>
    <div>Text 13</div>
    <span>Text 14</span>
    <div>Text 15</div>
</div>
در مثال فوق Text 2و Text 7 به رنگ قرمز نمایش می‌یابند.  
پشتیبانی در مرورگرها:

 Selector نسخه CSS
 3.2  9.6  9.0 3.5  4.0 :nth-child(n)  3

55- :nth-last-child(n)
تگی را انتخاب می‌کند که nامین فرزند والد خود از آخر باشد. به جای n می‌توان از مقادیر odd (فرزندان فرد)، even (فرزندان زوج) و an+b استفاده نمود.
<style>
    div.container :nth-last-child(2) {
        color: red;
    }
</style>
<div class="container">
    <h1>Text 1</h1>
    <span>Text 2</span>
    <p>Text 3</p>
    <div>Text 4</div>
    <div>Text 5</div>
    <div>
        <h1>Text 6</h1>
        <span>Text 7</span>
        <p>Text 8</p>
        <p>
            <span>Text 9</span>
        </p>
        <div>Text 10</div>
        <p>Text 11</p>
    </div>
    <h1>Text 12</h1>
    <div>Text 13</div>
    <span>Text 14</span>
    <div>Text 15</div>
</div>
در مثال فوق Text 14و Text 10 به رنگ قرمز نمایش می‌یابند.  
پشتیبانی در مرورگرها:

 Selector نسخه CSS
 3.2  9.6  9.0 3.5  4.0 :nth-last-child(n)  3

56- :first-of-type
تگی را انتخاب می‌کند که اولین تگ در بین هم نوعان خودش و در یک والد باشد. 
<style>
    div.container :first-of-type {
        color: red;
    }
</style>
<div class="container">
    <h1>Text 1</h1>
    <span>Text 2</span>
    <p>Text 3</p>
    <div>Text 4</div>
    <div>Text 5</div>
    <div>
        <h1>Text 6</h1>
        <span>Text 7</span>
        <p>Text 8</p>
        <p>
            <span>Text 9</span>
        </p>
        <div>Text 10</div>
        <p>Text 11</p>
    </div>
    <h1>Text 12</h1>
    <div>Text 13</div>
    <span>Text 14</span>
    <div>Text 15</div>
</div>
در مثال فوق Text 1، Text 2، Text 3، Text 4، Text 6، Text 7، Text 8، Text 9و Text 10 به رنگ قرمز نمایش می‌یابند.  
پشتیبانی در مرورگرها:

 Selector نسخه CSS
 3.2  9.6  9.0 3.5  4.0 :first-of-type  3

57- :last-of-type
تگی را انتخاب می‌کند که آخرین تگ در بین هم نوعان خودش و در یک والد باشد.
<style>
    div.container :last-of-type {
        color: red;
    }
</style>
<div class="container">
    <h1>Text 1</h1>
    <span>Text 2</span>
    <p>Text 3</p>
    <div>Text 4</div>
    <div>Text 5</div>
    <div>
        <h1>Text 6</h1>
        <span>Text 7</span>
        <p>Text 8</p>
        <p>
            <span>Text 9</span>
        </p>
        <div>Text 10</div>
        <p>Text 11</p>
    </div>
    <h1>Text 12</h1>
    <div>Text 13</div>
    <span>Text 14</span>
    <div>Text 15</div>
</div>
در مثال فوق Text 15، Text 14، Text 12، Text 11، Text 10، Text 9، Text 7، Text 6و Text 3 به رنگ قرمز نمایش می‌یابند.  
پشتیبانی در مرورگرها:

 Selector نسخه CSS
 3.2  9.6  9.0 3.5  4.0 :last-of-type  3

58- :only-of-type
تگی را انتخاب می‌کند که تنها تگ در بین هم نوعان خودش و در یک والد باشد.
<style>
    div.container :only-of-type {
        color: red;
    }
</style>
<div class="container">
    <h1>Text 1</h1>
    <span>Text 2</span>
    <p>Text 3</p>
    <div>Text 4</div>
    <div>Text 5</div>
    <div>
        <h1>Text 6</h1>
        <span>Text 7</span>
        <p>Text 8</p>
        <p>
            <span>Text 9</span>
        </p>
        <div>Text 10</div>
        <p>Text 11</p>
    </div>
    <h1>Text 12</h1>
    <div>Text 13</div>
    <span>Text 14</span>
    <div>Text 15</div>
</div>
در مثال فوق Text 3، Text 6، Text 7، Text 9 و Text 10 به رنگ قرمز نمایش می‌یابند.  
پشتیبانی در مرورگرها:

 Selector نسخه CSS
 3.2  9.6  9.0 3.5  4.0 :only-of-type  3

59- :nth-of-type(n)
تگی را انتخاب می‌کند که nامین تگ در بین هم نوعان خودش و در یک والد باشد. به جای n می‌توان از مقادیر odd (فرزندان فرد)، even (فرزندان زوج) و an+b استفاده نمود.
<style>
    div.container :nth-of-type(2) {
        color: red;
    }
</style>
<div class="container">
    <h1>Text 1</h1>
    <span>Text 2</span>
    <p>Text 3</p>
    <div>Text 4</div>
    <div>Text 5</div>
    <div>
        <h1>Text 6</h1>
        <span>Text 7</span>
        <p>Text 8</p>
        <p>
            <span>Text 9</span>
        </p>
        <div>Text 10</div>
        <p>Text 11</p>
    </div>
    <h1>Text 12</h1>
    <div>Text 13</div>
    <span>Text 14</span>
    <div>Text 15</div>
</div>
در مثال فوق Text 5، Text 9، Text 12 و Text 14 به رنگ قرمز نمایش می‌یابند.  
پشتیبانی در مرورگرها:

 Selector نسخه CSS
 3.2  9.6  9.0 3.5  4.0 :nth-of-type(n)  3

60- nth-last-of-type(n)
تگی را انتخاب می‌کند که nامین تگ از آخر در بین هم نوعان خودش و در یک والد باشد. به جای n می‌توان از مقادیر odd (فرزندان فرد)، even (فرزندان زوج) و an+b استفاده نمود.
<style>
    div.container :nth-last-of-type(2) {
        color: red;
    }
</style>
<div class="container">
    <h1>Text 1</h1>
    <span>Text 2</span>
    <p>Text 3</p>
    <div>Text 4</div>
    <div>Text 5</div>
    <div>
        <h1>Text 6</h1>
        <span>Text 7</span>
        <p>Text 8</p>
        <p>
            <span>Text 9</span>
        </p>
        <div>Text 10</div>
        <p>Text 11</p>
    </div>
    <h1>Text 12</h1>
    <div>Text 13</div>
    <span>Text 14</span>
    <div>Text 15</div>
</div>
در مثال فوق Text 1، Text 2، Text 9 و Text 13 به رنگ قرمز نمایش می‌یابند.  
پشتیبانی در مرورگرها:

 Selector نسخه CSS
 3.2  9.6  9.0 3.5  4.0 :nth-last-of-type(n)  3