ماجرای Discriminated Unions (DUs)  در .net  شبیه به یه افسانه شده بود که بالاخره انگار قراره توی C# 15  رنگ واقعیت به خودش بگیره. در این مطلب میخوایم بررسی کنیم که Union چی هست و چه مشکلاتی رو از ما میتونه برطرف کنه .

Union چیست ؟

Union یعنی یک متغیر بتونه "یکی از چند حالت مشخص" باشه. در حال حاضر توی سی‌شارپ وقتی می‌خوایم یه متغیر داشته باشیم که چند مدل دیتا بگیره، یا مجبوریم بریم سراغ object (که افتضاحه چون Type Safety نداره) یا از Inheritance یا ارث بری استفاده کنیم.

اما Union بهت اجازه میده دقیقاً تعریف کنی: « این متغیر من یا دایره است، یا مربع؛ نه چیز دیگه ! » یعنی محدودیت ایجاد می‌کنی و خیالت راحته که حالت سوم پیش نمیاد.

عملکرد Union ها در TypeScript چگونه است ؟

بچه‌هایی که فرانت کار می‌کنن یا با TypeScript سر و کار دارن، خیلی وقته دارن از این قابلیت لذت می‌برن. اونجا خیلی شیک می‌نویسن:

type Result = string | number;

این یعنی متغیر Result یا رشته‌ست یا عدد. نه چیز دیگه. حالا توی توابع هم خیلی راحت می‌تونن از این استفاده کنن و کامپایلر هم اگه بخوان چیزی غیر از این دوتا بهش بدن جلوشون رو میگیره .

فایده ی استفاده از Union ها

خداحافظی با Null Exception

دیگه لازم نیست برای اینکه بگیم "دیتا نبود" مقدار null برگردونیم که بعداً باعث NullReferenceException  بشه. می‌تونیم بگیم خروجی یا Data هست یا NotFound .

خوانایی فوق‌العاده

وقتی کد رو می‌خونی، دقیقاً می‌دونی با چه حالت‌هایی روبرو هستی.

امنیت در زمان کامپایل

اگه یه حالت رو توی switch فراموش کنی، خود ویژوال استودیو بهت اخطار میده. (Exhaustiveness checking)

کد تمیزتر

دیگه نیازی نیست برای هر کار کوچیکی کلی کلاس و ارث‌بری پیچیده بسازیم.

 

مدیریت سناریوهای مختلف (مثال کاربردی)

تصور کن یه متد داری که قراره یه کاربر رو از دیتابیس بگیره. توی حالت فعلی یا باید Exception برگردونی یا خروجی‌های متفاوت بدی. با قابلیت جدیدی که احتمالاً در C# 15 میاد (با فرض سینتکس‌های پیشنهادی)، کد یه چیزی شبیه به این میشه:

// تعریف حالت‌های ممکن برای خروجی

public union UserResult

{

case User FoundUser;

case ValidationError Errors;

case NotFound;

}

 

// استفاده در متد

public UserResult GetUser(int id)

{

if (id <= 0)

return new ValidationError("آیدی معتبر نیست");

 

var user = _db.Users.Find(id);

if (user == null)

return new NotFound();

 

return user; // حالت موفقیت آمیز

}

حالا موقع صدا زدن این متد، مجبوریم هر سه حالت رو مدیریت کنیم:

var result = GetUser(10);

 

string message = result switch

{

User u => $"کاربر پیدا شد: {u.Name}",

ValidationError e => $"خطا در ورودی: {e.Message}",

NotFound => "متاسفانه کاربر رو پیدا نکردیم!",

_ => throw new UnreachableException() // خیالت راحته که حالت دیگه‌ای نیست

}

 

جمع بندی

هرچند هنوز باید منتظر انتشار رسمی بمونیم، اما اضافه شدن Union Types به سی‌شارپ ۱۵ می‌تونه سبک کد زدن ما رو از حالت "کلاس‌محورِ محض" به سمت یه ساختار مدرن‌تر و امن‌تر ببره.

 فعلاً اگه به همچین ساختاری نیاز داری ، کتابخونه OneOf یکز از بهترین گزینه هاست تا مایکروسافت بالاخره این قابلیت رو به هسته زبان اضافه کنه!