أنواع Record: الأساسيات وبناء الجملة
صرّحوا عن record classes وrecord structs، وافهموا الصياغة الموضعية، وقارنوا بين records وclasses.
أنواع Record: الأساسيات وبناء الجملة درس مجاني في C# Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في C# Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة C# Academy 4 دروس في المجموع.
ما أنواع السجلات؟
السجلات (التي قُدّمت في C# 9) هي أنواع مرجعية مصممة لـالبيانات غير القابلة للتغيير مع دلالات القيمة. وهي تنشئ تلقائيًا مساواةً تستند إلى قيم الخصائص، وToString() قابلة للقراءة، وتدعم التغيير غير الهدّام باستخدام تعبيرات with.
صياغة السجل الموضعية
تُعد الصياغة الموضعية الشكل الأكثر إيجازًا. إذ تُنشأ الخصائص والمُنشئ والتفكيك والمساواة كلها من سطر واحد.
// All in one line:
public record Point(double X, double Y);
public record Person(string FirstName, string LastName, int Age);
// Generated automatically:
// - Primary constructor: new Point(1.0, 2.0)
// - Deconstruct: var (x, y) = point;
// - Equality: p1 == p2 compares X and Y values
// - ToString: "Point { X = 1, Y = 2 }"السجلات مقابل الفئات
تختلف السجلات والفئات أساسًا في المساواة الافتراضية والغرض المقصود. تستخدم السجلات المساواة البنيوية (القيم)، بينما تستخدم الفئات مساواة المرجع (الهوية).
var p1 = new Point(1, 2);
var p2 = new Point(1, 2);
var p3 = p1;
// Record: structural equality
Console.WriteLine(p1 == p2); // True — same values
Console.WriteLine(p1 == p3); // True — same values
// Compare with a class:
var c1 = new PointClass(1, 2);
var c2 = new PointClass(1, 2);
Console.WriteLine(c1 == c2); // False — different referencesسجلات البنى
أضاف C# 10 النوع record struct، وهو سجل من نوع قيمة. وله ميزات المساواة وToString نفسها الموجودة في فئات السجلات، لكنه يُخصَّص على المكدس مثل البنى.
// Record struct: value type, stack-allocated
public record struct Color(byte R, byte G, byte B);
var red = new Color(255, 0, 0);
var red2 = new Color(255, 0, 0);
Console.WriteLine(red == red2); // True — value equality
// Readonly record struct: fully immutable
public readonly record struct Coord(double Lat, double Lng);التعريف القياسي للسجل مع جسم
يمكن أن تحتوي السجلات على جسم كامل، مما يتيح إضافة الخصائص المحسوبة والطُرق وإجراء التحقق في المُنشئ، مع الاحتفاظ بالمساواة وToString التلقائيتين.
public record Person(string FirstName, string LastName)
{
// Computed property
public string FullName => $"{FirstName} {LastName}";
// Validation in constructor
public Person : this(FirstName, LastName)
{
if (string.IsNullOrWhiteSpace(FirstName))
throw new ArgumentException("FirstName required");
}
// Method
public Person WithUpperCase() =>
this with { FirstName = FirstName.ToUpper(), LastName = LastName.ToUpper() };
}الوراثة مع السجلات
تدعم السجلات الوراثة. ويضيف السجل المشتق مزيدًا من الخصائص ويشارك في قواعد المساواة نفسها؛ فلا يتساوى سجلان إلا إذا تطابقت أنواعهما وجميع قيمهما.
public record Shape(string Color);
public record Circle(string Color, double Radius) : Shape(Color);
public record Rectangle(string Color, double Width, double Height) : Shape(Color);
var c1 = new Circle("red", 5.0);
var c2 = new Circle("red", 5.0);
var r1 = new Rectangle("red", 5.0, 3.0);
Console.WriteLine(c1 == c2); // True
Console.WriteLine(c1 == r1); // False — different typesخصائص السجل غير الموضعية
لا تقتصر السجلات على المعلمات الموضعية. يمكنك الجمع بين الخصائص الموضعية والخصائص المُضافة يدويًا، واستخدام مهيئات الخصائص لتحديد القيم الافتراضية.
public record Order
{
public int Id { get; init; }
public string CustomerName { get; init; } = "";
public List<OrderLine> Lines { get; init; } = new();
public DateTime CreatedAt { get; init; } = DateTime.UtcNow;
public OrderStatus Status { get; init; } = OrderStatus.Pending;
}
// Initialization:
var order = new Order
{
Id = 42,
CustomerName = "Alice"
// Other props use defaults
};التفكيك
تنشئ السجلات الموضعية تلقائيًا طريقة Deconstruct، مما يتيح تفكيكها في عمليات التعيين ومطابقة الأنماط.
public record Point(double X, double Y);
var p = new Point(3.0, 4.0);
// Deconstruction
var (x, y) = p;
Console.WriteLine($"x={x}, y={y}");
// In switch:
string Describe(Point pt) => pt switch
{
(0, 0) => "Origin",
(double x, 0) => $"On X-axis at {x}",
(0, double y) => $"On Y-axis at {y}",
var (px, py) => $"Point ({px}, {py})"
};السجلات بصفتها DTOs
تُعد السجلات خيارًا ممتازًا لـ DTOs الخاصة بطلبات واستجابات API. فهي غير قابلة للتغيير وقابلة للتسلسل، كما تبسّط المساواة التي تُنشأ تلقائيًا عملية الاختبار.
// API request/response records
public record CreateProductRequest(
string Name,
decimal Price,
int Stock);
public record ProductResponse(
int Id,
string Name,
decimal Price,
int Stock,
DateTime CreatedAt);
// In controller:
app.MapPost("/products", (CreateProductRequest req, ProductService svc) =>
{
var product = svc.Create(req.Name, req.Price, req.Stock);
return Results.Created($"/products/{product.Id}",
new ProductResponse(product.Id, product.Name,
product.Price, product.Stock,
product.CreatedAt));
});مساواة السجلات في اختبارات الوحدات
تجعل مساواة القيم السجلات مثالية لتأكيدات اختبارات الوحدات. يمكنك مقارنة السجلات المتوقعة والفعلية باستخدام == أو Assert.Equal من دون مقارنات مخصصة.
[Fact]
public async Task CreateOrder_ReturnsCorrectResponse()
{
var response = await _client.PostAsJsonAsync("/orders",
new CreateOrderRequest(CustomerId: 1, ProductId: 5, Quantity: 2));
var order = await response.Content.ReadFromJsonAsync<OrderResponse>();
// Simple equality check — no custom IEqualityComparer needed!
Assert.Equal(
new OrderResponse(Id: order!.Id, Status: "Pending", Total: 99.98m),
order);
}اختبار سريع
ما دلالات المساواة التي تستخدمها سجلات C# افتراضيًا؟
مراجعة: أساسيات أنواع السجلات
أهم النقاط:
- السجلات أنواع مرجعية تستخدم المساواة بالقيمة (المساواة البنيوية) افتراضيًا
- تنشئ الصياغة الموضعية المُنشئ والتفكيك والمساواة وToString
record struct(في C# 10) هو نوع من القيمة البديلة- تدعم السجلات الوراثة؛ ويجب أن يتطابق النوع أيضًا حتى تتحقق المساواة
- وهي مناسبة جدًا لـ DTOs وعقود API وتأكيدات اختبارات الوحدات
- أضف الخصائص المحسوبة والطُرق في كتلة الجسم إلى جانب المعلمات الموضعية
الأسئلة الشائعة
هل درس «أنواع Record: الأساسيات وبناء الجملة» مجاني؟
نعم — نص درس «أنواع Record: الأساسيات وبناء الجملة» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة C# Academy، انتقل إلى CoddyKit PRO. تتضمن دورة C# Academy 4 دروس في المجموع.
ماذا ستتعلم في «أنواع Record: الأساسيات وبناء الجملة»؟
صرّحوا عن record classes وrecord structs، وافهموا الصياغة الموضعية، وقارنوا بين records وclasses. تتمرن على C# Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ C# Academy؟
لا تُشترط خبرة سابقة. C# Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.
كم من الوقت يستغرق درس «أنواع Record: الأساسيات وبناء الجملة»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس C# Academy هذا؟
نعم. كل درس في C# Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- أنواع Record: الأساسيات وبناء الجملة
- عدم قابلية التغيير باستخدام init وwith
- مساواة القيم والتفكيك
- Records في التصميم المستند إلى النطاق