> ## Documentation Index
> Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt
> Use this file to discover all available pages before exploring further.

# C# Record

A `record` in C# is a type declaration modifier that instructs the compiler to synthesize members for value-based equality, non-destructive mutation, and formatted string representation. By default, a `record` is a reference type (implicitly a `record class`), but it can also be declared as a value type (`record struct`).

## Syntax Variations

**Positional Syntax**
Declaring a record with a primary constructor automatically generates public, `init`-only properties (for reference types) or mutable properties (for `record struct` types).

```csharp theme={"dark"}
public record Person(string FirstName, string LastName);
```

**Nominal Syntax**
Records can be declared using standard property syntax, allowing for explicit control over mutability and access modifiers.

```csharp theme={"dark"}
public record Product
{
    public string Name { get; set; }
    public decimal Price { get; init; }
}
```

**Record Structs**
Applying the `record` modifier to a `struct` provides the same synthesized members for value types. Positional `record struct` properties are mutable by default unless explicitly marked `readonly`.

```csharp theme={"dark"}
public readonly record struct Point(double X, double Y);
```

## Compiler-Synthesized Members

When a `record` is compiled, the C# compiler automatically generates several members to enforce its behavior:

**1. Value Equality (`IEquatable<T>`)**
The compiler overrides `Object.Equals(Object)` and implements `IEquatable<T>.Equals(T)`. Two record instances are equal if they share the exact same run-time type and all their property and field values are equal. The compiler also overloads the `==` and `!=` operators.

*Note: Equality is **shallow**.* If a record contains reference type properties (such as arrays, lists, or other classes), equality checks will only compare the memory addresses (references) of those objects, not their underlying data.

```csharp theme={"dark"}
var p1 = new Person("John", "Doe");
var p2 = new Person("John", "Doe");
bool isEqual = p1 == p2; // Evaluates to true
```

**2. Hash Code Generation**
The compiler overrides `GetHashCode()`, computing a hash based on the values of all instance fields and properties. This ensures that records with identical data produce identical hash codes, making them safe for use as keys in hash-based collections like `Dictionary<TKey, TValue>`.

**3. Non-Destructive Mutation (`with` Expression)**
Records support the `with` expression, which creates a new instance of the record with specified properties modified.

*Note: Mutation is **shallow**.* Reference type properties are copied by reference rather than deeply cloned. Modifying the internal state of a referenced object in the new record will affect the original record.

The compiler implements this differently depending on the record type:

* **`record class`**: The compiler generates a hidden virtual `<Clone>$` method and a protected copy constructor to instantiate the new object.
* **`record struct`**: The compiler relies on standard value-type assignment (a bitwise memory copy) and does *not* generate a `<Clone>$` method or a copy constructor.

```csharp theme={"dark"}
var p3 = p1 with { LastName = "Smith" };
// p1 remains ("John", "Doe"), p3 is ("John", "Smith")
```

**4. Formatting (`ToString` and `PrintMembers`)**
The compiler overrides `ToString()` to output a formatted string containing the type name and the names and values of its public properties. To handle the string construction, it generates a `PrintMembers` method:

* **`record class`**: Generates a `protected virtual PrintMembers` method, which can be overridden in derived records to customize the output.
* **`record struct`**: Because structs cannot participate in inheritance and cannot have `protected` or `virtual` members, the compiler generates a `private`, non-virtual `PrintMembers` method.

```csharp theme={"dark"}
Console.WriteLine(p1); 
// Output: Person { FirstName = John, LastName = Doe }
```

**5. Deconstruction**
If positional syntax is used, the compiler generates a `Deconstruct` method, allowing the record's properties to be unpacked directly into individual variables.

```csharp theme={"dark"}
var (first, last) = p1;
```

## Inheritance Rules and Equality Contracts

* A `record class` can inherit from another `record class`, but it cannot inherit from a standard `class`.
* A standard `class` cannot inherit from a `record class`.
* A `record struct` cannot participate in inheritance (as structs in C# are implicitly sealed), but it can implement interfaces.
* To maintain symmetric equality across inheritance hierarchies, the compiler generates a virtual `EqualityContract` property that returns the `Type` object of the record. When evaluating equality, the `EqualityContract` of both operands must match. Therefore, a base record and a derived record with identical property values will evaluate as unequal.

<div
  style={{ 
display: "flex", 
justifyContent: "space-between", 
alignItems: "center", 
maxWidth: "754px", 
padding: "1rem 0",
marginBottom: "24px"
}}
>
  <span style={{ fontWeight: "bold", fontSize: "1.25rem", color: "var(--tw-prose-headings)", fontFamily: "Inter, ui-sans-serif, system-ui, sans-serif" }}>Tired of Poor C# Skills? Fix That With Deep Grasping!</span>

  <a
    href="https://syntblaze.com"
    target="_blank"
    style={{ 
  marginLeft: "24px",
  textDecoration: "none", 
  backgroundColor: "#007AFF",
  color: "#ffffff", 
  padding: "6px 16px", 
  borderRadius: "16px",
  fontSize: "0.9rem",
  fontWeight: "600",
  textAlign: "center",
  transition: "background-color 0.2s ease"
}}
  >
    Learn More
  </a>
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/skill-tracking.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=b9b0305c93bb501c9e767b5c76c88835" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/skill-tracking.png" />

  <img src="https://mintcdn.com/syntblazellc/23tyuOzaWS88qFlc/images/nuggets.png?fit=max&auto=format&n=23tyuOzaWS88qFlc&q=85&s=c86c80197299762989e9b882419b2109" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/nuggets.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/bite-sized-exercises.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=a65f9a38c37ff28ab73ed783c53c60e3" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/bite-sized-exercises.png" />
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap", marginTop: "12px" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/mastery-chain.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=748a1763454713e679260fbb95f154a2" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/mastery-chain.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-previews.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=242f61448ff5dd6deaaab2dccc13b507" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-previews.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-explanations.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=cf0fc1c31f9cd0fc26716781be05fbc9" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-explanations.png" />
</div>
