#C

ویژگی های جدید در C# 10

در این مقاله قصد داریم نگاهی به موارد جدید در سی شارپ 10 بیاندازیم. NET 6 از آخرین نسخه سی شارپ پشتیبانی می کند و برای استفاده از آن در پروژه های خود به جدیدترین .NET 6 SDK یا Visual Studio 2022 نیاز داریم.

 

Record Structs در سی شارپ 10

با شروع C# 9، می‌توانیم از کلمه کلیدی Record برای تعریف اشیاء نوع مرجع غیرقابل تغییر «out-of-the-box» در کد خود استفاده کنیم.

از این به بعد، می‌توانیم مقدار نوع records را با کلمات کلیدی record struct اعلام کنیم تا مانند سایر انواع مقدار رفتار کنند. اگر struct را حذف کنیم، انواع مرجع (reference types) خواهند بود، اما می‌توانیم صریح‌ تر باشیم و از record class برای رسیدن به همان رفتار استفاده کنیم.

Custom Interpolated String Handlers

Custom Interpolated String Handlers نوعی است که اصطلاح placeholder را در یک رشته درون‌یابی (interpolated) پردازش می‌کند:

[InterpolatedStringHandler]
public ref struct CustomInterpolatedStringHandler
{
StringBuilder builder;
public CustomInterpolatedStringHandler(int literalLength, int formattedCount)
{
builder = new StringBuilder(literalLength);
}
public void AppendLiteral(string s)
{
builder.Append(s);
}
public void AppendFormatted<T>(T t)
{
if (t is string)
{
var s = t?.ToString() ?? string.Empty;
var notToken = "not ";
var index = s.IndexOf(notToken);
builder.Append(index < 0 ? s : s.Remove(index, notToken.Length));
}
else
{
builder.Append(t?.ToString());
}
}
public string GetFormattedText() => builder.ToString();
}

ما فقط به این نکته توجه می کنیم که به سازنده ای با حداقل دو ورودی نیاز داریم. ورودی اول در سازنده، ثابت‌های صحیحی هستند که توسط کامپایلر جمع‌آوری شده‌اند، که نشان‌دهنده طول واقعی درونیابی و تعداد اجزای درون‌یابی هستند.

با این پیاده سازی، می توانیم Program کلاس را تغییر دهیم:

var attribute = "not awesome";
var processedMessage = ProcessMessage($"IranDotNetCore is {attribute}.");
string ProcessMessage(CustomInterpolatedStringHandler builder) => builder.GetFormattedText();

اکنون، در نتیجه، مقدار processedMessage برابر است با : "IranDotNetCore is awesome." و می‌توانیم ببینیم که نحوه نمایش placeholder را که تغییر کرده، چگونه پیاده سازی کردیم.

Global Using Directives در سی شارپ 10

ما نیازی به using namespace ها در ابتدای هر فایل نداریم. ما می توانیم using namespace هایی را که در حال حاضر در فایل Program و CustomInterpolatedStringHandler فایل های خود داریم استخراج کنیم.

برای انجام این کار، اجازه دهید Usings.cs فایل را با تمام دستورالعمل های استفاده کننده ایجاد کنیم:

global using System.Diagnostics;
global using System.Runtime.CompilerServices;
global using System.Text;
global using WhatsNewInCSharp10;

با این روش می توانیم تمام global using ها را در یک فایل استخراج کرده و در پروژه خود استفاده کنیم.

اما این همه ماجرا نیست. یک ویژگی جدید در NET 6 SDK. پشتیبانی از global using directives مجازی است. این یکی از دلایلی است که ما می توانیم Minimal APIs را تنها با چهار خط کد راه اندازی کنیم.

Extended Property Patterns در سی شارپ 10

ما قادریم به خواص یا فیلدهای تودرتو در یک الگوی ویژگی ارجاع دهیم. می توانید در مقاله Extended Property Patterns در C# در مورد آن بیشتر بخوانید .

بهبود و ارتقا Structure Types در سی شارپ 10

به منظور پشتیبانی record struct، برای انواع struct normal نیز پیشرفت هایی دریافت کردیم.انواع struct می توانند سازنده بدون پارامتر داشته باشند و می توانند یک فیلد یا ویژگی نمونه را در اعلان آن مقداردهی اولیه کنند:

public struct IranDotNetCore
{
// Parameterless constructor with property initialization 
public IranDotNetCore()
{
Size = 10;
}
// Initialization of the property at its declaration
public int Size { get; set; } = 10;
}

اعلام File-scoped Namespace در سی شارپ 10

ما دیگر نیازی به قرار دادن کد خود بلوک های namespace نداریم:

namespace WhatsNewInCSharp10;
public struct IranDotNetCore
{
…
} 

همانطور که می بینیم، ما آن {...} برای فضای نامی که در نسخه های قبلی سی شارپ داشتیم نداریم. 

بهبود Lambda Expression در سی شارپ 10

اکنون عبارات Lambda بیشتر شبیه متدها و توابع محلی هستند. آنها می توانند یک نوع طبیعی داشته باشند و کامپایلر یک نوع نماینده را از عبارت Lambda یا یک گروه متد استنتاج می کند. همچنین، می‌توانیم ویژگی‌ها (attributes) را به عبارات Lambda اعمال کنیم. برای نشان دادن این بهبودها در عمل، اجازه دهید یک متد Lambda بنویسیم:

var lambda = [DebuggerStepThrough]() => "Hello world";

در نسخه قبلی سی شارپ، با یک خطای کامپایلر مواجه می‌شویم که نمی‌توانیم عبارت lambda را به یک متغیر با تایپ ضمنی (implicitly-typed) اختصاص دهیم و ویژگی‌های lambda پشتیبانی نمی‌شوند.

رشته های درون یابی ثابت (Constant Interpolated Strings)  در سی شارپ 10

در C# 10 می‌توانیم ثابت هایی از رشته‌های ثابت درون‌یابی (interpolated constant strings) تولید کنیم.

برای نشان دادن آن، "IranDotNetCore is {constantAttribute}"$ اجازه دهید رشته درون یابی شده را به صورت یک const مقداردهی اولیه کنیم :

const string constantAttribute = "awesome";
const string constantMessage = $"IranDotNetCore is {constantAttribute}.";

ما می توانیم این کار را انجام دهیم اگر مکان نگهدار ما نیز یک Const باشد.

انواع Record می توانند ToString را مهر و موم کنند در سی شارپ 10

هنگامی که ما از انواع record در کد خود استفاده می کنیم، کامپایلر پیاده سازی یک متد ToString را برای ما ایجاد می کند.

بیایید یک سلسله مراتب (hierarchy) ساده از انواع record ایجاد کنیم:

public record Article(string Author, string Title);
public record IranDotNetCoreArticle(string Author, string Title, string Comment) : Article(Author, Title);

از آنجایی که نمی‌خواهیم Comment در نمایش رکورد (record) IranDotNetCoreArticle گنجانده شود، سی شارپ 10 به ما اجازه می‌دهد که sealed اصلاح‌کننده را اضافه کنیم، که مانع از ایجاد یک ToString پیاده‌سازی برای هر رکورد مشتق شده توسط کامپایلر می‌شود:

public record Article(string Author, string Title)
{
public sealed override string ToString()
{
return $"{Author}: {Title}";
}
}

و اکنون می‌توانیم ToStringمتد را درIranDotNetCoreArticle فراخوانی کنیم :

var  IranDotNetCoreArticleRepresentation = new  IranDotNetCoreArticle("Author", "Title", "Comment").ToString();

در نتیجه، ارزش IranDotNetCoreArticleRepresentation برابر "Author: Title" است و ما به هدف خود برای ارائه ثابت articles خود دست یافته ایم.

تخصیص و اعلام در همان ساختارشکنی

نکته جالب این است که بتوانیم تخصیص ها و اعلان ها را هنگام ساختارشکنی Tuple های خود ترکیب کنیم:

var articles = (new Article("Author", "Title"), 
new IranDotNetCoreArticle("Author", "Title", "Comment"));
var article = new Article("Another author", "Another title");
(article, IranDotNetCoreArticle  iranDotNetCoreArticle ) = articles;

پس از ساختارشکنی، خصوصیات article.Author و article.Title  به ترتیب مقادیر"Author" و "Title" را نگه می دارند. همچنین، می‌توانیم از مقدار اولیه متغیر iranDotNetCoreArticle بیشتر در کد خود استفاده کنیم و خصوصیات را با هم مقایسه کنیم:

var areAuthorsEqual = article.Author ==  iranDotNetCoreArticle.Author;

قبل از C# 10، ما فقط می‌توانستیم همه متغیرها را به متغیرهای موجود اختصاص دهیم یا متغیرهای تازه تعریف شده را مقداردهی اولیه کنیم.

نتیجه :

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

ممنون که تا انتهای مقاله با ما همراه بودید، امیدواریم این مقاله برای شما مفید بوده باشه.