رکوردها در C#
رکوردها (Records) در سیشارپ از نسخه 9 معرفی شدند و هدف اصلی آنها سادهسازی تعریف انواع دادهای (Data Types) با تأکید بر روی داده و نه هویت (Identity) است. در معماری نرمافزار و توسعه سیستمهای بزرگ، اغلب نیاز داریم دادههایی را مدل کنیم که تغییرناپذیر (Immutable) باشند و برابری آنها بر اساس مقدار (Value Equality) سنجیده شود، نه بر اساس مرجع (Reference Equality). اینجاست که رکوردها نقش کلیدی ایفا میکنند.
رکوردها به ما اجازه میدهند دادهها را به شکل مختصر و امن تعریف کنیم، در حالی که از امکاناتی مانند مقایسه ساختاری (Structural Equality)، سازندههای پیشفرض، متد ToString خودکار و قابلیت with برای ایجاد نسخههای جدید از یک شیء استفاده میکنیم. این ویژگیها باعث میشوند رکوردها گزینهای عالی برای ساخت DTOها (Data Transfer Objects)، مدلهای دامنه (Domain Models) در DDD و حتی الگوریتمهایی شوند که بر پایه تغییرناپذیری طراحی شدهاند.
در این آموزش، شما با سینتکس پایه رکوردها، کاربرد آنها در ساختارهای داده و الگوریتمها، و همچنین اصول شیءگرایی در سیشارپ آشنا خواهید شد. علاوه بر این، بهترین شیوهها (Best Practices)، مشکلات رایج و نکات بهینهسازی در کار با رکوردها بررسی خواهد شد. یادگیری رکوردها به شما کمک میکند در طراحی سیستمهای پایدار، امن و بهینه در سطح معماری نرمافزار موفقتر عمل کنید.
مثال پایه
textusing System;
public record محصول(string نام, decimal قیمت);
public class Program
{
public static void Main()
{
var p1 = new محصول("لپتاپ", 45000000m);
var p2 = new محصول("لپتاپ", 45000000m);
Console.WriteLine(p1);
Console.WriteLine($"آیا محصولات برابرند؟ {p1 == p2}");
}
}
در مثال بالا رکوردی به نام محصول تعریف شده است که دارای دو ویژگی نام و قیمت است. استفاده از رکورد به جای کلاس باعث میشود تا نیازی به نوشتن دستی متدهای Equals، GetHashCode یا ToString نداشته باشیم. در واقع، سیشارپ بهطور خودکار این متدها را برای رکوردها تولید میکند.
هنگام ساخت p1 و p2، به دلیل اینکه مقدار ویژگیهای آنها یکسان است، عبارت p1 == p2 مقدار true برمیگرداند. این موضوع نشان میدهد رکوردها از برابری ساختاری پشتیبانی میکنند، در حالی که کلاسها به طور پیشفرض تنها برابری مرجع را در نظر میگیرند.
متد ToString نیز به طور خودکار نمایش قابل خواندن از شیء تولید میکند، به طوری که خروجی شامل نام نوع و مقادیر ویژگیها است. این ویژگی در هنگام دیباگ پروژههای بزرگ بسیار مفید است.
به طور کلی، رکوردها به توسعهدهندگان امکان میدهند دادهها را بهصورت ایمن، خوانا و کوتاهتر مدل کنند. این قابلیت بهخصوص در سناریوهایی مثل طراحی DTO در معماری لایهای، انتقال داده بین سرویسها و پیادهسازی الگوریتمهایی که تغییرناپذیری در آنها اهمیت دارد، بسیار کاربردی است.
مثال کاربردی
textusing System;
using System.Collections.Generic;
public record مشتری(string نام, string ایمیل);
public record سفارش(int شناسه, مشتری مشتری, decimal مبلغ);
public class Program
{
public static void Main()
{
var مشتری1 = new مشتری("مریم رضایی", "[[email protected]](mailto:[email protected])");
var سفارش1 = new سفارش(1, مشتری1, 1500000m);
var سفارش2 = سفارش1 with { مبلغ = 2000000m };
List<سفارش> لیست_سفارشات = new() { سفارش1, سفارش2 };
foreach (var s in لیست_سفارشات)
{
Console.WriteLine(s);
}
Console.WriteLine($"آیا سفارشها برابرند؟ {سفارش1 == سفارش2}");
}
}
در کار با رکوردها رعایت اصول طراحی بسیار مهم است. نخستین اصل، بهرهگیری از خاصیت تغییرناپذیری است. توصیه میشود همیشه رکوردها را بهصورت Immutable نگه داریم و تغییرات را از طریق کلیدواژه with انجام دهیم. این کار باعث کاهش خطاهای ناشی از تغییر وضعیت در پروژههای بزرگ میشود.
یکی از اشتباهات رایج، استفاده از رکوردها در شرایطی است که نیاز به هویت یکتا (Unique Identity) داریم. در این مواقع بهتر است از کلاسها استفاده شود. همچنین، در مجموعههای بزرگ داده (Large Collections) باید دقت کرد که محاسبه برابری ساختاری هزینهبر است و میتواند منجر به افت کارایی شود.
از نظر خطایابی، خروجی ToString پیشفرض رکوردها ابزاری ارزشمند است، اما باید مراقب بود دادههای حساس در آن نمایش داده نشوند. در حوزه امنیت، هنگام کار با رکوردهایی که شامل اطلاعات محرمانه هستند، بهتر است ToString بازنویسی (Override) شود.
در بهینهسازی عملکرد نیز بهتر است رکوردها را برای دادههای سبک و انتقالی بهکار ببریم و در صورت نیاز به مدیریت منابع پیچیده، به سراغ کلاسها یا ساختارهای دیگر برویم.
📊 جدول مرجع
سیشارپ Element/Concept | Description | Usage Example |
---|---|---|
رکورد موقعیتی | تعریف مختصر ویژگیها به صورت Immutable | public record محصول(string نام, decimal قیمت); |
عملگر with | ایجاد نسخه جدید شیء با تغییر بخشی از داده | var سفارش2 = سفارش1 with { مبلغ = 2000m }; |
برابری ساختاری | مقایسه مقادیر ویژگیها به جای مرجع | p1 == p2 |
ToString خودکار | ایجاد نمایش متنی خوانا برای دیباگ | Console.WriteLine(p1); |
کاربرد در DTO | انتقال امن داده بین لایهها | public record مشتریDTO(string نام, string ایمیل); |
در جمعبندی، رکوردها ابزاری قدرتمند در سیشارپ هستند که امکان طراحی دادههای تغییرناپذیر، خوانا و امن را فراهم میکنند. آنها کدنویسی را سادهتر کرده و از نوشتن کدهای تکراری جلوگیری میکنند. مهمترین نکته این است که رکوردها جایگزین کلاسها نیستند، بلکه مکمل آنها در طراحی سیستمها به شمار میروند.
رکوردها بهویژه در معماریهای مبتنی بر پیام (Message-driven) و طراحی دامنهمحور (DDD) جایگاه ویژهای دارند. یادگیری آنها به شما کمک میکند تا در پروژههای واقعی مثل توسعه APIها، طراحی سرویسهای مایکروسرویسی و مدیریت دادههای انتقالی بهترین نتیجه را بگیرید.
گامهای بعدی برای یادگیری میتواند شامل بررسی عمیقتر تغییرناپذیری، استفاده از رکوردها در کنار LINQ، و مطالعه الگوهای طراحی مانند CQRS و Event Sourcing باشد. برای تمرین عملی، میتوانید پروژههایی ایجاد کنید که در آنها مدلهای دامنه بهصورت رکورد تعریف شدهاند.
به عنوان منابع تکمیلی، مطالعه مستندات رسمی مایکروسافت و بررسی پروژههای متنباز که از رکوردها در مقیاس بزرگ استفاده کردهاند، میتواند درک شما از این قابلیت را عمیقتر کند.
🧠 دانش خود را بیازمایید
Test Your Knowledge
Test your understanding of this topic with practical questions.
📝 دستورالعملها
- هر سوال را با دقت بخوانید
- بهترین پاسخ را برای هر سوال انتخاب کنید
- میتوانید آزمون را هر چند بار که میخواهید تکرار کنید
- پیشرفت شما در بالا نمایش داده میشود