init-Only Setters
Create properties settable only at initialization.
init-Only Setters is a free C# Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C# Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
init-Only Setters
An init accessor lets a property be set during object construction (including object initializers) but makes it read-only afterward. The shape is { get; init; }.
using System;
class Point {
public int X { get; init; }
public int Y { get; init; }
}
var p = new Point { X = 3, Y = 4 };
Console.WriteLine(p.X + "," + p.Y); // 3,4Set Only at Initialization
After the object is built, assigning to an init property is a compile error, guaranteeing immutability post-construction.
using System;
class Config {
public string Name { get; init; }
}
var c = new Config { Name = "prod" };
// c.Name = "dev"; // compile error
Console.WriteLine(c.Name); // prodObject Initializers Still Work
The big win over a read-only get-only property is that init supports the object initializer syntax, so you do not need a constructor for every property.
using System;
class Settings {
public bool DarkMode { get; init; }
public int FontSize { get; init; }
}
var s = new Settings { DarkMode = true, FontSize = 14 };
Console.WriteLine(s.DarkMode + " " + s.FontSize); // True 14Combining with Constructors
You can set init properties from a constructor and also allow initializer overrides.
using System;
class User {
public string Role { get; init; } = "guest";
public User() { }
}
var u = new User { Role = "admin" };
Console.WriteLine(u.Role); // adminDefault Values
init properties can have default initializers that apply unless overridden during construction.
using System;
class Options {
public int Retries { get; init; } = 3;
}
Console.WriteLine(new Options().Retries); // 3
Console.WriteLine(new Options { Retries = 5 }.Retries); // 5init vs set
A set accessor allows mutation any time; init restricts assignment to the construction phase. Choose init for immutable-after-creation data.
using System;
class Mutable { public int V { get; set; } }
class Frozen { public int V { get; init; } }
var m = new Mutable { V = 1 };
m.V = 2; // allowed
Console.WriteLine(m.V); // 2init with Validation
You can implement an explicit init body with a backing field to validate the assigned value.
using System;
class Percentage {
private int _value;
public int Value {
get => _value;
init => _value = (value < 0 || value > 100)
? throw new ArgumentOutOfRangeException()
: value;
}
}
Console.WriteLine(new Percentage { Value = 80 }.Value); // 80init in Records
Positional record properties are init-only by default, which is why records are immutable yet support with copies.
using System;
record Account(string Id, decimal Balance);
var a = new Account("A1", 100m);
Console.WriteLine(a.Balance); // 100Nested Object Initializers
init works with nested object initializers, letting you build complex immutable graphs in one expression.
using System;
class Address { public string City { get; init; } }
class Person { public string Name { get; init; } public Address Home { get; init; } }
var p = new Person { Name = "Lin", Home = new Address { City = "Oslo" } };
Console.WriteLine(p.Name + " / " + p.Home.City); // Lin / Osloinit and Inheritance
Derived classes can set base init properties via object initializers, since the construction phase spans the whole object.
using System;
class Base { public int Id { get; init; } }
class Item : Base { public string Name { get; init; } }
var i = new Item { Id = 1, Name = "Pen" };
Console.WriteLine(i.Id + " " + i.Name); // 1 PenPutting It Together
An immutable DTO built entirely with init properties and an object initializer.
using System;
class OrderDto {
public int Id { get; init; }
public string Customer { get; init; }
public decimal Amount { get; init; }
}
var o = new OrderDto { Id = 7, Customer = "Ada", Amount = 49.9m };
Console.WriteLine(o.Id + " " + o.Customer + " " + o.Amount); // 7 Ada 49.9Quick Check
Test your understanding of init-only setters.
Recap
You learned init-only setters.
{ get; init; }allows assignment only during construction.- Object initializers work with
initproperties. - You can add validation via an explicit
initbody. - Record positional properties are
initby default.
Frequently asked questions
Is the “init-Only Setters” lesson free?
Yes — the full text of “init-Only Setters” is free to read here on the web, and the C# Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C# Academy course, upgrade to CoddyKit PRO.
What will I learn in “init-Only Setters”?
Create properties settable only at initialization. You practise C# Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start C# Academy?
No prior experience is required. C# Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “init-Only Setters” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this C# Academy lesson?
Yes. Every C# Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.