ویژگی های جدید در C# 7
دوشنبه 25 مرداد 1395در این مقاله قصد داریم چند ویژگی از ویژگی های جدید و مفید 7#C مانند Record type ، Tuple ، Pattern Matching را همراه با مثال توضیح دهیم.
تاپل(Tuple) چیست؟
تاپل ها برای گروهبندی موقت مقادیر مورد استفاده قرار میگیرند . شما می توانید یک تاپل را با یک کلاس POCO مقایسه کنید ، و به جای تعریف آن به عنوان یک کلاس، می توانید آن را درfly تعریف کنید. در زیر یک مثال از چنین کلاسی است:
class PropertyBag { public int Id {get; set;} public string Name {get; set;} } var myObj = new PropertyBag { Id = 1, Name = "test};
در مثال بالا در واقع نیازی به نام گذاری نبود.در کار شاید برای ساختارهای موقتی نیازی به نام گذاری نداشته باشیم.
Tuples ها راهی برای ساختن ساختارهای موقتی روی fly هستند که نیازی به ساختن کلاس ها ندارند.
چرا؟
رایج ترین دلیل برای داشتن یک گروه از مقادیری که به صورت موقت گروه بندی می شوند ، مقادیر بازگشتی متعدد از یک متد است. در حال حاضر، چند راه برای انجام این کار در C # وجود دارد:
پارامترهای خروجی (Out parameters)
public void GetLatLng(string address, out double lat, out double lng) { ... } double lat, lng; GetLatLng(myValues, out lat, out lng); Console.WriteLine($"Lat: {lat}, Long: {lng}");
استفاده از out-parameters (پارامتر خروجی) چندین مشکل دارد:
• نمیتواند از این برای async-methods استفاده شود.
• مجبور به اعلام پارامترهای upfront است (باید نوع مشخص شود ، نمیتوان از Var استفاده کرد )
نوع تاپل (Tuple-type)
در حال حاظر در #C چند Tuple-type وجود دارد که مانند native tuple عمل میکنند.
شما میتوانید متد قبل را به صورت زیر بازنویسی کنید:
public Tuple<int, int> GetLatLng(string address) { ... } var latLng = GetLatLng("some address"); Console.WriteLine($"Lat: {latLng.Item1}, Long: {latLng.Item2}");
این نوع ،معایب پارامتر خروجی را ندارد، اما نتیجه کد و نتیجه تاپل برای پروپرتی با نام هایی شبیه به ITEM1 و ITEM2 مبهم است .
کلاس / ساختار (Class / struct)
شما همچنین میتوانید یک نوع جدید تعریف کنید و از آن به صورت نوع بازگشتی استفاده کنید.
struct LatLng{ public double Lat; public double Lng;} public LatLng GetLatLng(string address) { ... } var ll= GetLatLng("some address"); Console.WriteLine($"Lat: {ll.Lat}, Long: {ll.Lng}");
این مورد هیچ یک از معایب پارامتر خروجی و نوع تاپل را ندارد ، اما نسبتا طولانی و در overhead بی معنی است.
چگونه؟
چند مورد مختلف برای تاپل ، که توسط C# 7 Tuple استفاده میشود ، وجود دارد.
نوع بازگشتی تاپل(Tuple return types):
شما می توانید نوع بازگشتی متعدد برای یک تابع مشخص کنید ، در اکثر مواقع برای مشخص کردن نوع ورودی های متعدد ، Syntax مشابه است . (method arguments)
public (double lat, double lng) GetLatLng(string address) { ... } var ll = GetLatLng("some address"); Console.WriteLine($"Lat: {ll.lat}, Long: {ll.lng}");
تاپل های درون خطی (Inline tuples):
شما همچنین می توانید تاپل های درون خطی ایجاد کنید:
var ll = new (double lat, double lng) { lat = 0, lng = 0 };
ساختار زدایی تاپل (Tuple deconstruction):
ممکن است که شما نخواهید به همه ی بسته های نرم افزاری دسترسی داشته باشید، و مستقیما مقادیر داخلی را دریافت کنید.بجای دسترسی به پروپرتی های تاپل (به عنوان مثال انواع تاپل بازگشتی) ، از تاپل destructure مستقیما استفاده کنید.
(var lat, var lng) = GetLatLng("some address"); Console.WriteLine($"Lat: {lat}, Long: {lng}");
انواع رکورد(Record types)
Record types ،مجموعه ای ساده از پروپرتی هاست ،و یک نوع داده (data type) که فقط شامل پروپرتی ها است.
چرا؟
اغلب کلاسها و یا struct ها ،صرفا مجموعه ای از پروپرتی ها هستند. آنها هنوز هم نیاز به اعلام(declare) کامل که کاملا طولانی است ، دارند . کلاس زیر نشان می دهد که یک کلاس با 3 پروپرتی نیاز به کمی متن(text) برای اعلام دارد:
class MyPoint { int _x; int _y; int _z; MyPoint(int x, int y, int z){ this._x = x; this._y = y; this._z = z; } public int X {get{ return this._x;}} public int Y {get{ return this._y;}} public int Z {get{ return this._z;}} }
چگونه؟
باتایپ رکورد شما می توانید کد بالا را در یک خط بنویسید:
class Point(int X, int Y, int Z);
• چند مورد بیشتر در باره ی آن:
کلاس ،به طور خودکار < IEquatable<Point را اجرا میکند ، که به معنی این است که می توانید ، بجای مقایسه مرجع دو رکورد types based ، مقادیر آنها را مقایسه کنید
متد ToString -برای خروجی مقادیر در رکورد است.
تطبیق الگو(Pattern Matching)
چیست؟
باتایپ رکورد در تعامل است . تطبیق الگو بدان معنی است که شما می توانید نوع داده را تغییر دهید ، و باید یک یا statement های دیگر را اجرا کنید.
چرا؟
با وجودی که تطبیق الگو بسیار شبیه if/else است ، دارای مزایای خاص نیز میباشد
شما می توانید تطبیق الگو را بر روی هر نوع داده انجام دهید، حتی در حالی که if/else همیشه نیاز اولیه برای مطابقت داشته باشد.
تطبیق الگو می تواند مقادیری از expression خود را استخراج کند.
چگونه؟
به مثال زیر توجه کنید:
class Geometry(); class Triangle(int Width, int Height, int Base) : Geometry; class Rectangle(int Width, int Height) : Geometry; class Square(int width) : Geometry; Geometry g = new Square(5); switch (g) { case Triangle(int Width, int Height, int Base): WriteLine($"{Width} {Height} {Base}"); break; case Rectangle(int Width, int Height): WriteLine($"{Width} {Height}"); break; case Square(int Width): WriteLine($"{Width}"); break; default: WriteLine("<other>"); break; }
Non-nullable reference types
چیست؟
مقادیر Nullable در C# 2.0 معرفی شدند.این موارد به خصوص همراه با کلاس های <Nullable<T مفید می باشند.
Non-nullable reference types برعکس این ویژگی ها هستند. این ویژگی به شما اجازه می دهد تا نوع reference هایی را ایجاد کنید که به صورت قطعی، null نخواهند بود.
چرا؟
NullReference exceptions بسیار رایج هستند.
دو مشکل وجود دارد: اول این که شما null بودن آن ها را چک نمی کنید و به همین خاطر ممکن است با runtime exceptions مواجه شوید.
اگر بخواهید این موارد را بررسی کنید، با مشکل دیگری روبرو می شوید. کد شما طولانی و خسته کننده می شود و از هدفی که قبلا داشته اید، دور می شوید.
توانایی تعریف یک reference type در قالب non-nullable بر این مشکلات غلبه میکند.
چگونه؟
نکته:این syntax هنوز در حال استفاده است و ممکن است تغییر کند..syntax های احتمالی دیگری نیز وجود دارند که هنوز فرم قطعی برای انها مشخص نشده است.
زمانی که ما از واژه error استفاده می کنیم مشخص نیست که یک خطای کامپایلری است یا فقط یک warning.
اول از همه ، syntax مطلوب این است که reference types ها non-nullable باشند.
این یک تقارنی بین reference و value types را اماده میکند.
int a; //non-nullable value type int? b; //nullable value type string c; //non-nullable reference type string? d; //nullable reference type
هرچند،ملیون ها خط در در #C وجود دارد
------------------------------------------
int a; //non-nullable value type int? b; //nullable value type string! c; //non-nullable reference type string d; //nullable reference type
استفاده از nullable و non-nullable types بر روی کامپایلر اثر میگذارد.
MyClass a; // Nullable reference type MyClass! b; // Non-nullable reference type a = null; // OK, this is nullable b = null; // Error, b is non-nullable b = a; // Error, n might be null, s can't be null WriteLine(b.ToString()); // OK, can't be null WriteLine(a.ToString()); // Warning! Could be null! if (a != null) { WriteLine(a.ToString); } // OK, you checked WriteLine(a!.Length); // Ok, if you say so
استفاده از این syntax ایرادی ندارد اما ممکن است که برای ساختمان های داده generic مشکل ایجاد کند.
// The Dictionary is non-nullable but string, List and MyClass aren't
Dictionary<string, List<MyClass>>! myDict; // روشی مناسب برای declare کردن همه ی تایپ های non-nullable است. Dictionary<string!, List<MyClass!>!>! myDict;
این کد بالا مقداری از نظر خوانایی سخت است.بنا براین shortcut را اماده کرده ایم:
// Typing ! in front of the type arguments makes all types non-nullable Dictionary!<string, List<MyClass>> myDict;
توابع محلی C# 7
چیست؟
توانایی declare کردن متد ها و تایپ ها در block scope.
چرا؟
این عمل با استفاده از Func and Action types با anonymous methods انجام میشود.
• Generics
• ref and out parameters
• params
تابع های Local تماما مانند normal methods هستند با این تفاوت که Local function ها در حوزه خودشان تعریف میشوند
چگونه؟
public int Calculate(int someInput) { int Factorial(int i) { if (i <= 1) return 1; return i * Factorial(i - 1); } var input = someInput + ... // Other calcs return Factorial(input); }
C# 7 Immutable Types
چیست؟
object های تغییر نا پذیر oblect هایی هستند که بعد از ساخته شدن تغییر نمیکنند.
Why?
oblect های تغییر ناپذیر چه مزایایی دارند:
• Inherently thread-safe
• به سادگی ایجاد می شوند
• ساده بودن برای موازی کردن کد ها
• Reference هایی که به object های تغییر ناپذیر اشاره میکنند میتوانند cached بشوند.و تغییر نخواهند کرد.
در حال حاظر میتوانید یک immutable objects را تعریف کنید.
public class Point { public Point(int x, int y) { x = x; Y = y; } public int X { get; } public int Y { get; } }
هنگامی که یک immutable object را معین میکنیم، مشکل انجاست که مفهوم واضحی ندارد.
ممکن است یکی setter اضافه کند و استفاده کنندگان از این تایپ، همچنان انتظار immutability داشته باشند.
به این ترتیب می توان از آن ها، نتایج مختلفی را انتظار داشت.
چگونه؟
نکته: این syntax هم اکنون در حال استفاده است اما توصیه اساسی ما به شما اضافه کردن کلمه کلیدی immutable به syntax های رایج است.
public immutable class Point { public Point(int x, int y) { x = x; Y = y; } public int X { get; } public int Y { get; } }
وقتی شما از immutable types استفاده میکنید ، ویژگی مفیدی در اختیار خواهید داشت که به شما اجازه ساخت نمونه های جدید مبتنی بر نمونه های مختلف قبلی را می دهد.
var a = new Point(2, 5); var b = a with { X = 1};
- C#.net
- 2k بازدید
- 2 تشکر