بررسی ويژگی های اضافه شده به نسخه 9 زبان سی شارپ

بررسی ويژگی های اضافه شده به نسخه 9 زبان سی شارپ

شرکت مایکروسافت، دات نت فریم ورک و زبان سی شارپ را در حدود سال 2002 میلادی به دنیای فناوری اطلاعات و توسعه ی نرم افزار معرفی کرد و به سرعت محبوبیت فراوانی بین توسعه دهندگان نرم افزار پیدا کرد و به یکی از ابزارهای مهم توسعه دهندگان تبدیل شد. در دات نت فریم ورک می توان با زبان های مختلفی مانند سی شارپ، وی بی دات نت و اف شارپ برنامه نویسی کرد که مهم ترین شان سی شارپ می باشد. در طول 20 سال اخیر شرکت مایکروسافت در نسخه های مختلفی که از زبان سی شارپ ارائه داده است، ویژگی های جدیدی به آن اضافه کرده است. در ماه نوامبر سال 2020 میلادی، شرکت مایکروسافت نسخه ی 9 زبان سی شارپ را همراه با دات نت نسخه ی 5 معرفی کرد. برای استفاده از ویژگی های جدید اضافه شده به نسخه ی 9 زبان سی شارپ، حتما باید از نسخه ی 5 دات نت استفاده کنید. در این نوشتار قصد داریم نگاهی داشته باشیم به ويژگی های جدید نسخه ی 9 زبان سی شارپ. پس بیایید شروع کنیم.

شروع کار با سی شارپ 9

برای کار با نسخه ی 9 زبان سی شارپ باید موارد زیر را روی سیستم خود نصب داشته باشید:

  • ویژوال استدیو نسخه ی 2019 یا ویژوال استدیو کد
  • NET 5 SDK. (نسخه 5 دات نت)

موارد بالا را می توانید از آدرس های زیر دریافت نمایید.

https://visualstudio.microsoft.com/vs/older-downloads/

https://dotnet.microsoft.com/en-us/download/dotnet/5.0

دقت داشته باشید از نسخه ی 5 به بعد، Net Core. و دات نت فریم ورک وجود ندارد و فریم ورک دات نت مایکروسافت به اسم دات نت (Net.) شناخته می شود و قرار است هر سال نسخه ی جدیدی از آن ارائه شود. 

پس از اجرای ویژوال استدیوی 2019، پروژه ای با دات نت 5 ایجاد کنید. همان طور که گفتیم برای استفاده از ویژگی های جدید نسخه ی 9 زبان سی شارپ، حتما باید حداقل نسخه 5 دات نت را در اختیار داشته باشید (در زمان نوشتن این نوشتار نسخه 6 دات نت ارائه شده است). پس از ساختن پروژه، کامپایلر به صورت خودکار نسخه ی زبان سی شارپ را با توجه به این که از دات نت 5 استفاده می کنید، روی نسخه ی 9 تنظیم خواهد کرد. 

ویژگی Init only setters

در نسخه ی 3 زبان شی شارپ تعریف property در کلاس ها با ارائه ویژگی auto implemented properties بسیار آسان تر شد چون کامپایلر به صورت خودکار backing field مورد نظر را برایمان خواهد ساخت و ما باید با استفاده از کلمات کلیدی get و set خصوصیات را تعریف کنیم. 

یکی از ویژگی های جدید اضافه شده به نسخه ی 10 زبان سی شارپ، Init only setters نام دارد. این ویژگی، این قابلیت را به خصوصیات یا property های یک کلاس اضافه می کند که مقدار آن ها در زمان مقداردهی اولیه یا initialization تنظیم شده و پس از آن دیگر نتوان مقدار آن ها را تغییر داد. 

عملا property مورد نظر به یک property فقط خواندنی یا read only تبدیل خواهد شد. به این نوع property ها، immutable یا غیر قابل تغییر هم گفته می شوند زیرا پس از انتصاب مقدار به آن ها،  مقدار آن ها قابلیت تغییر نخواهد داشت. برای این منظور کلمه ی کلیدی جدیدی به نام init اضافه شده است که از آن می توان در تعریف property استفاده کرد. 

فرض کنید کلاس PointReadOnlyAfterCreation را به صورت زیر تعریف کرده ایم. 

using System;

namespace ObjectInitializers
{
    class PointReadOnlyAfterCreation
    {
        public int X { get ; init ; } // public int X { get ; set ; }
        public int Y { get ; init ; } // public int Y { get ; set ; }

        public void DisplayStats()
        {
           Console.WriteLine(" InitOnlySetter: [{0}, {1}] ", X, Y) ;
        }

        public PointReadOnlyAfterCreation(int xVal , int yVal)
        {
           X = xVal ;
           Y = yVal ;
        }

        public PointReadOnlyAfterCreation() { }
    }
}

این کلاس دو خصوصیت X و  Y که محل یک نقطه را تعیین می کنند، درون خودش تعریف کرده است. می خواهیم این دو خصوصیت، پس از این که تعریف شدند و مقدار گرفتند، نتوان مقدار آن ها را تغییر داد. یک راه حل این است که بخش set آن را به صورت private set تعریف کنیم تا به صورت خصوصی درآمده و نتوان آن را از بیرون تغییر داد. ولی مشکلی که این روش دارد آن است که property را تنها در سازنده می توان مقداردهی کرد و در زمان مقداردهی به خصوصیات شی (object initializer‌) نمی توان آن را تغییر داد.

پس در راه حلی که در نسخه ی 9 به زبان سی شارپ اضافه شده است، همان طور که می بینید به جای این که از کلمه set در زمان تعریف خصوصیت استفاده کنیم، از کلمه ی init استفاده شده است. زمانی که از این کلمه استفاده می کنیم، تنها می توان در سازنده کلاس و یا زمان مقداردهی اولیه خصوصیات شی یا object initializer‌ به آن مقدار داد و اگر در طول برنامه بخواهیم مقدار آن را تغییر دهیم با خطای زیر مواجه می شویم.

Init - only property or indexer ' PointReadOnlyAfterCreation.X ' can only be assigned in an object initializer, or on ' this ' or ' base' in an instance constructor or an ' init' accessor . 

در قطعه کد زیر، نحوه ی استفاده از کلاس PointReadOnlyAfterCreation نشان داده شده است. همان طور که می بینید خصوصیات X و Y در شی firstReadonlyPoint در سازنده، مقدار گرفته اند و در شی secondReadonlyPoint در مرحله ی object initializer به آن ها مقدار تخصیص داده شده است و پس از ساختن شی، اگر بخواهیم مقدار آن ها را تغییر دهیم با خطای زمان کامپایل رو به رو خواهیم شد.

namespace C_Sharp9
{
    internal class Program
    {
        static void Main(string[] args)
        {
           PointReadOnlyAfterCreation firstReadonlyPoint = new PointReadOnlyAfterCreation(20, 20) ;
           firstReadonlyPoint.DisplayStats() ;

           PointReadOnlyAfterCreation secondReadonlyPoint = new PointReadOnlyAfterCreation
           {
               X = 30 ,
               Y = 30
           };
           secondReadonlyPoint.DisplayStats() ;

           secondReadonlyPoint.X = 10 ; // Error
           secondReadonlyPoint.Y = 10 ; // Error
        }
    }
}

نکته ای که باید به آن توجه داشته باشید این است که، حتی اگر درون کلاس متدی داشته باشید و آن متد هم بخواهد مقدار X یا Y را تغییر بدهد، با خطا مواجه خواهد شد. دلیل آن هم این است که چون این نوع property ها را تنها در سازنده یا object initializer می توان تغییر داد و با اعضای خصوصی یا private متفاوت هستند. در واقع می خواهیم آن ها را غیر قابل تغییر یا Immutable کنیم. 

public void SetX(int x)
{
    this.X = x ; // Error
}

ویژگی Top level statements

قبل از معرفی کردن این ویژگی در نسخه ی 9 زبان سی شارپ، همه ی برنامه هایی که در این زبان نوشته می شد، دارای متدی به نام ()Main بودند که entry point یا نقطه ی ورود برنامه محسوب می شدند. مثلا فرض کنید می خواهیم متن ساده‌ی  !Hello World را روی صفحه چاپ کنیم. پس باید کد زیر را بنویسیم.

using System ;

namespace HelloWorld
{
    class Program
    {
        static void Main(string[] args)
        {
           Console.WriteLine(" Hello World ! ") ;
                     . . . 
        }
    }
}

همان طور که می بینید برای نوشتن یک متن ساده باید این مقدار کد اضافی نوشت. یعنی یکسری دستورهای using، تعریف فضای نام، تعریف کلاس و تعریف متد Main. در نسخه ی 9 زبان سی شارپ ویژگی Top level statements اضافه شد تا کد های اضافی را حذف کنیم. با استفاده از این ویژگی، تعریف فضای نام، تعریف کلاس Program و متد ()Main حذف خواهند شد و برنامه به صورت زیر در خواهد آمد و دیگر از آن کد های اضافی خبری نخواهد بود. با این ویژگی جدید، برای کسی که تازه شروع به یادگیری زبان سی شارپ کرده است و هنوز با مفاهیمی مانند static و  .  .  .  آشنا نیست کار بسیار راحت تر خواهد شد.

Using System;

Console.WriteLine(" * * * * * My First C# App * * * * * ");
Console.WriteLine(" Hello World ! ") ;
Console.WriteLine();

Console.ReadLine();

هنگام استفاده از این ویژگی، باید به قوانین زیر توجه کنید:

  • تنها یک فایل در کل application باید حاوی ویژگی Top level statements باشد، در غیر این صورت با خطا مواجه می شوید.
  • زمانی که از ویژگی Top level statements استفاده می کنید، برنامه نباید entry point یا نقطه ورود دیگری داشته باشد.
  • ویژگی Top level statements نباید درون تعریف یک namespace قرار بگیرد.
  • در طول استفاده از ویژگی Top level statements، به پارامتر args که آرایه ای از رشته ها است دسترسی خواهیم داشت و از طریق آن می توانیم مواردی را از ورودی دریافت کنیم.
  • در زمان استفاده از ویژگی Top level statements، با استفاده از کلمه ی return می توان از برنامه خارج شد.
  • توابع و متد هایی که تعریف می شوند، به صورت توابع محلی یا local functions برای Top level statements در نظر گرفته خواهند شد.
  • سایر انواعی که می توان در یک کلاس تعریف کرد (مانند enum  ها)، باید حتما پس از آخرین خط دستورات واقع در Top level statements تعریف شوند در غیر این صورت با خطا مواجه می شوید. مانند قطعه کد زیر:
using System;

Console.WriteLine(" * * * * * My First C# App * * * * * ");
Console.WriteLine(" Hello World ! ") ;
Console.WriteLine();
Console.ReadLine();

enum Color
{
    Red,
   Green, 
    Blue,
}

ویژگی Target type new expressions

در نسخه‌ی 3 زبان سی شارپ  امکان استفاده از کلمه ی کلیدی var مهیا شد. با استفاده از آن، کامپایلر نوع متغیر را براساس مقداری که در آن ریخته می شود، حدس خواهد زد که به آن target typing گفته می شود. ویژگی جدیدی که در این نسخه به زبان سی شارپ اضافه شده است، تقریبا عکس کلمه var است. 

زمانی که می خواهیم با استفاده از کلمه ی کلیدی new از یک کلاس نمونه ای بسازیم، باید بعد از کلمه ی new، اسم کلاس را بیاوریم. در نسخه ی 9 این عبارت کمی کوتاه شده است و نیازی به نوشتن اسم کلاس بعد از کلمه ی new نیست. البته به شرطی که قبلا اسم کلاس را آورده باشیم. مثلا کلاس زیر را داریم.

Public class Car
{
    public Car() { }
    public Car(string color , int year)
    {
       Color = color ;
       ConstructionYear = year ;
    }

    public string Color { get ; set ; }
    public int ConstructionYear { get ; set ; }
}

در این جا می خواهیم از آن نمونه هایی ایجاد کنیم. می توان به دو روش زیر این کار را انجام داد.

Car myPrettyCar = new() ;
Car myPrettyCar2 = new Car() ;

وقتی نام کلاس قبل از نام شی آورده می شود، در نسخه ی جدید می توان نام کلاس را بعد از کلمه ی new حذف کرد و عبارت کوتاه تر خواهد شد و کامپایلر نوع آن را از نوعی که برای شی ذکر کرده ایم استخراج خواهد کرد. به این ویژگی Improved Target Typing گفته می شود. توجه کنید اگر نوع را قبل از نام شی ذکر نکنیم و به جای آن از کلمه ی var استفاده کنیم با خطای زیر مواجه خواهیم شد.

Var myPrettyCar = new() ; // Error
There is no target type for ' new()'

در ادامه به مواردی خواهیم پرداخت که در آن ها می توان از این ویژگی استفاده کرد.

می توان مانند قبل، خصوصیات شی را مقداردهی کرده و یا سازنده ی آن را فراخوانی کرد.

Car myPrettyCar3 = new() { Color = " Red ", ConstructionYear = 2020 } ;
Car myPrettyCar4 = new(" Yellow " , 2018) ;

ازاین قابلیت در لیست ها هم می توان استفاده کرد.

Var carList = new List<Car>
{
    new () ,
    new (" Red " , 2020) ,
} ;

از این روش می توان در فراخوانی متدها استفاده کرد.

Public void Adopt(Car p)
{
    // . . .
}

public void CallerMethod()
{
    this.Adopt(new(" Car1 " , 2020));
}

نکته ای که در مورد کلمه ی کلیدی var وجود دارد این است که از var نمی توان در فیلد های یک کلاس استفاده کرد و مجبوریم کل عبارت را بنویسیم مانند عبارت زیر:

private List<Dictionary<string, Car>> cars = new List<Dictionary<string, Car>>() ;

اما با استفاده از این ویژگی می توان این عبارت را به صورت زیر کوتاه کرد:

private List<Dictionary<string, Car>> cars = new () ;

ویژگی foreach زدن روی انواع مختلف

در سی شارپ با استفاده از دستور foreach می توان روی اعضای یک شی (مانند یک لیست یا یک آرایه) پیمایش انجام داد و تک به تک اعضای آن شی را خواند. foreach را نمی توان روی هر شی ای به کار برد چون foreach باید بداند که اعضا را به چه ترتیبی و چگونه بخواند. در واقع دستور foreach باید این توانایی را داشته باشد که بداند که آیا عضوی در شی مورد نظر وجود دارد یا خیر و هم چنین آیا به انتهای اعضای شی رسیده است یا خیر. 

برای این که یک شی این قابلیت را داشته باشد، باید درون خودش یک شی دیگری داشته باشد به نام شمارنده یا Enumerator. شمارنده باید سه وظیفه ی اصلی زیر را داشته باشد.

  1. MoveNext
  2. Current
  3. Reset

برای این که عضوی خوانده شود، ابتدا با استفاده از MoveNext از وجود یا عدم وجود عضوی در شی مورد نظر، اطمینان حاصل می کنیم. به وسیله ی Current عضو جاری خوانده می شود و برای این که به عضو اول برگردیم و اعضا را از اول پیمایش کنیم از Reset کمک می گیریم. 

در دات نت مجموعه ی این متد ها در واسط IEnumerator جمع آوری شده است. برای این که شی ای این قابلیت را داشته باشد، تا به وسیله ی foreach پیمایش شود، باید واسط IEnumerable را پیاده سازی کند. داخل این واسط متدی وجود دارد به نام GetEnumerator که شمارنده ی مورد نظر را بر می گرداند.

تا قبل از سی شارپ 9، برای این که کلاسی این توانایی را داشته باشد که اشیا آن کلاس در foreach استفاده شود، باید حتما آن کلاس را ویرایش کرد و واسط IEnumerable را در آن پیاده سازی کرد. در سی شارپ 9 ویژگی جدیدی اضافه شده است تا بدون این که نیاز باشد آن کلاس را ویرایش کنیم، این قابلیت را به آن اضافه کرد تا در foreach استفاده شده و اعضای آن را پیمایش کنیم. این مورد زمانی خیلی کار آمد خواهد بود که کد کلاس را در اختیار نداشته باشیم و بخواهیم این توانایی را به کلاس اضافه کنیم.

فرض کنید کلاس زیر را دارید. این کلاس دارای 5 عضو بوده و می خواهیم اشیایی که از این نوع هستند را در foreach استفاده کرده و اعضای آن را چاپ کنیم.

Namespace C_Sharp9
{
    public class Choices
    {
        public string FirstChoice { get ; set ; }
        public string SecondChoice { get ; set ; }
        public string ThirdChoice { get ; set ; }
        public string FourthChoice { get ; set ; }
        public string FifthChoice { get ; set ; }
        . . .
    }
}

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

Namespace C_Sharp9
{
    public class ChoicesEnumerator
    {
        public string[] _choices = new string[5] ;

        int position = -1 ;

        public ChoicesEnumerator(Choices choices)
        {
           _choices[0] = choices.FirstChoice ;
           _choices[1] = choices.SecondChoice ;
           _choices[2] = choices.ThirdChoice ;
           _choices[3] = choices.FourthChoice ;
           _choices[4] = choices.FifthChoice ;
        }

        public bool MoveNext()
        {
           position++ ;
            return position < _choices.Length ;
        }

        public string Current
        {
            get
           {
               try
               {
                   return _choices[position] ;
               }
               catch (IndexOutOfRangeException)
               {
                   throw new InvalidOperationException() ;
               }
           }
        }
    }
}

شمارنده دارای دو متد اصلی به نام های MoveNext و Current می باشد که توسط foreach مورد استفاده قرار خواهد گرفت. در قدم بعدی باید کلاس Choices را به گونه ای تغییر دهیم که حتما متدی به نام GetEnumerator داشته باشد (‌چون واسط IEnumerable  دارای متدی با این نام می باشد). خروجی این متد باید نوعی باشد که دارای دو متد به نام های MoveNext و Current باشد. پس کلاس Choices را به صورت زیر تغییر خواهیم داد.

Namespace C_Sharp9
{
    public class Choices
    {
        public string FirstChoice { get ; set ; }
        public string SecondChoice { get ; set ; }
        public string ThirdChoice { get ; set ; }
        public string FourthChoice { get ; set ; }
        public string FifthChoice { get ; set ; }

        public ChoicesEnumerator GetEnumerator()
        {
            return new ChoicesEnumerator(this) ;
        }
    }
}

تا قبل از سی شارپ 9 سوالی که وجود داشت این بود که اگر کد کلاس در اختیار ما نبود (در یک کتابخانه یا فریم ورک ثانویه قرار داشت) و نمی توانستیم کد کلاس را ویرایش کنیم، به چه نحوی می توانستیم این قابلیت را به کلاس اضافه کنیم؟ از نسخه ی 9 زبان سی شارپ این توانایی اضافه شد که بدون ویرایش کد کلاس و با استفاده از قابلیت Extension Method که از قبل وجود داشت، شمارنده را به کلاس مورد نظرمان اضافه کنیم.

مثلا کلاس را به حالت اول خودش یعنی به صورت زیر بر می گردانیم.

Namespace C_Sharp9
{
    public class Choices
    {
        public string FirstChoice { get ; set ; }
        public string SecondChoice { get ; set ; }
        public string ThirdChoice { get ; set ; }
        public string FourthChoice { get ; set ; }
        public string FifthChoice { get ; set ; }
        . . .
    }
}

در مرحله ی بعد کلاس ChoicesExtensions را تعریف می کنیم و درون آن متدی اضافه می کنیم به نام GetEnumerator  و آن را به کلاس Choices اضافه خواهیم کرد.

Namespace C_Sharp9
{
    public static class ChoicesExtensions
    {
        public static ChoicesEnumerator GetEnumerator(this Choices choices)
        {
            return new ChoicesEnumerator(choices) ;
        }
    }
}

به این وسیله توانستیم بدون این که کد کلاس Choices را تغییر دهیم آن را در foreach استفاده کنیم.

Var choices = new Choices
{
   FirstChoice = " Orange " ,
   SecondChoice = " Blue " ,
   ThirdChoice = " Green " ,
   FourthChoice = " Cyan " ,
   FifthChoice = " Grey "
};

foreach (var choice in choices)
{
   Console.WriteLine(choice) ;
}
. . . 

بهبود ويژگی Pattern matching

در نسخه ی 7 زبان سی شارپ ویژگی Pattern Matching معرفی شد. با استفاده از این ویژگی عبارت ها، متغیر ها و شی ها را بررسی خواهیم کرد که آیا دارای شرایط خاصی بوده و آیا از الگوی خاصی پیروی خواهند کرد یا خیر. به عنوان مثال وقتی می خواهیم بفهمیم که آیا شی ای اینترفیس خاصی را پیاده سازی کرده است یا از کلاس خاصی مشتق شده است می توان از عمگر is استفاده کرد. در نسخه های ۷ به بعد زبان سی شارپ بهبود هایی روی این نوع عملیات اتفاق افتاده است. در بسیاری از موارد استفاده از این ویژگی، مقدار کدی که نیاز است نوشته شود را کم کرده و منجر به خوانا تر شدن کد خواهد شد. در ادامه تغییراتی که در این نسخه در مورد این ویژگی رخ داده است را بررسی خواهیم کرد.

یکی از انواع Pattern Matching ها، type pattern است. با استفاده از آن، براساس نوع یک شی یا عبارت در زمان اجرای برنامه تصمیم هایی گرفته می شود. به عنوان مثال قطعه کد زیر را در نظر بگیریم. می خواهیم براساس نوع متغیر o پیام های جداگانه ای در خروجی چاپ کنیم. در این جا چون نوع آن رشته است، پس پیام " it's a string " در خروجی چاپ خواهد شد.

using System;

object o = "hello" ;
string message = o switch
{
    string _ => " it's a string " ,
    int _ => " it's an int " ,
    _ => " it's something else "
} ;

Console.WriteLine(message) ;

Console.ReadLine() ;

اگر دقت کرده باشید وقتی در حال بررسی نوع متغییر هستیم، با قرار دادن علامت discard (ـ)، در حال تعریف متغییری هستیم تا مقداری در آن ریخته شود تا با مقدار o مقایسه شود. در نسخه ی 9 زبان سی شارپ این نیازمندی حذف شده و نیازی به آوردن علامت discard نیست و در نتیجه کد بالا به کد زیر تغییر پیدا خواهد کرد.

using System;

object o = false ;
string message = o switch
{
    string => " it's a string " ,
    int => " it's an int ",
    _ => " it's something else "
};

Console.WriteLine(message) ;

Console.ReadLine() ;

در این نسخه امکان استفاده از is not اضافه شده است. تا قبل از نسخه ی 9 اگر می خواستیم نقیض عملگر is را بررسی کنیم، باید از عملگر ! (not) استفاده می کردیم مانند کد زیر:

using System ;

object o = false ;

if(!(o is string))
{
   Console.WriteLine(" not a string ") ;
}

Console.ReadLine() ;

اما در این نسخه، می توان این کد را خوانا تر نوشته و به جای استفاده از عملگر ! از is not استفاده نماییم. به این صورت:

using System;

object o = false; 

if(o is not string)
{
   Console.WriteLine(" not a string ") ;
}

Console.ReadLine() ;

توجه داشته باشید که خروجی هر دو قطعه کد به یک صورت خواهد بود.

در راستای خوانا تر کردن کد ها و نزدیک کردن آن به زبان انگلیسی، کلمه های کلیدی or و and اضافه شده اند. مثلا انواع زیر را در نظر بگیرید.

public interface IDrawable
{
    void draw() ;
}
public class Rectangle : IDrawable
{
    public void draw()
    {
       Console.WriteLine(" drawing rectangle . . . ") ;
    }
}
public class Circle : IDrawable
{
    public void draw()
    {
       Console.WriteLine(" drawing circle . . . ") ;
    }
}

و هم چنین قطعه کد زیر را در نظر بگیرید.

IDrawable shape = new Circle() ;

if ((shape is IDrawable) && !(shape is Rectangle))
{
   Console.WriteLine(" Shape is Circle . . . ") ;
}

Console.ReadLine() ;

همان طور که مشاهده می کنید این عبارت به زبان محاوره ای انگلیسی نزدیک نیست و نیاز به بررسی دارد. با اضافه شدن کلمه های کلیدی or و and می توان آن را به صورت زیر باز نویسی کرد.

using System;

IDrawable shape = new Circle();

if (shape is IDrawable and not Rectangle)
{
    Console.WriteLine(" Shape is Circle . . . ") ;
}

Console.ReadLine() ;

این قطعه کد ضمن خوانا تر شدن کد، مانند یک متن ساده ی انگلیسی به نظر می آید. این کلمات را می توان با سایر نوع ها مانند نوع int هم استفاده کرد. مثلا می توان کد زیر را با کد بعد از آن جایگزین کرد.

var number = 15 ;
if (number > 5 && number < 20)
{

}

var number = 15 ;
if (number is > 5 and < 20)
{

}

هم چنین می توان این نوع مقایسه کردن را در دستور switch هم به کار برد. مانند تکه کد زیر:

int number = 0 ;
switch (number)
{
    case <= 0 :
       Console.WriteLine(" Less than or equal to 0 ") ;
        break;
    case > 0 and <= 10 :
       Console.WriteLine(" More than 0 but less than or equal to 10 ") ;
        break ;
    default:
       Console.WriteLine(" More than 10 ") ;
        break;
}

Console.ReadLine() ;

در این مقاله نگاهی انداختیم به ویژگی هایی که در نسخه‌ی 9 زبان سی شارپ اضافه شده است. امیدوارم مرور این ویژگی ها در خوانا تر نوشتن کد به شما عزیزان کمک کند. شما می توانید برای آشنایی با ویژگی های نسخه 10 زبان سی شارپ به مقاله مروری بر ویژگی های اضافه شده به نسخه 10 زبان #C در وبلاگ سکان آکادمی مراجعه کنید.

از بهترین نوشته‌های کاربران سکان آکادمی در سکان پلاس


online-support-icon