C
C#8mo ago

❔ what's a usecase where "readonly" would be prefered to property with an init setter?

init can be used in both constructor and in object initializers. readonly only in constructor.
6 Replies
arion
arion8mo ago
Fields are usually declared as private / protected while properties are generally the opposite. A property like:
public string Name { get; init; }
public string Name { get; init; }
can be modified to include some additional processing when fetching the underlying string set initially like:
public class User
{
private string _name;
public required string Name
{
get => _name.ToUpper();
init => _name = value;
}
}
public class User
{
private string _name;
public required string Name
{
get => _name.ToUpper();
init => _name = value;
}
}
A potential issue with the case above is, it results in a new string allocation each time the property is called. You could also do
public class User
{
private string _name;
public required string Name
{
get
{
Console.WriteLine($"Property {nameof(Name)} was accessed with value: {_name}");
return _name;
}
init => _name = value;
}
}
public class User
{
private string _name;
public required string Name
{
get
{
Console.WriteLine($"Property {nameof(Name)} was accessed with value: {_name}");
return _name;
}
init => _name = value;
}
}
I would also like to note that for Dependency Injection, readonly is used a lot for injected objects, eg.
public class SomeService : ISomeService
{

private readonly ISomeRepository _someRepository;
public SomeService(ISomeRepository someRespository)
{
_someRepository = someRepository;
}
}
public class SomeService : ISomeService
{

private readonly ISomeRepository _someRepository;
public SomeService(ISomeRepository someRespository)
{
_someRepository = someRepository;
}
}
Also, depending on the placement of the field (I believe) the value of the field is set before the constructor is invoked and works like a static context.
MODiX
MODiX8mo ago
arion
REPL Result: Success
public class MyClass
{
public readonly int MyInt = GetInt();

private static int GetInt()
{
Console.WriteLine("Field was initialized");
return 69;
}

public MyClass()
{
Console.WriteLine("Constructor was initialized");
}

public readonly int MySecondInt = GetSecondInt();

private static int GetSecondInt()
{
Console.WriteLine("Second field was initialzied");
return 420;
}
}

new MyClass();
public class MyClass
{
public readonly int MyInt = GetInt();

private static int GetInt()
{
Console.WriteLine("Field was initialized");
return 69;
}

public MyClass()
{
Console.WriteLine("Constructor was initialized");
}

public readonly int MySecondInt = GetSecondInt();

private static int GetSecondInt()
{
Console.WriteLine("Second field was initialzied");
return 420;
}
}

new MyClass();
Console Output
Field was initialized
Second field was initialzied
Constructor was initialized
Field was initialized
Second field was initialzied
Constructor was initialized
Compile: 672.859ms | Execution: 79.615ms | React with ❌ to remove this embed.
arion
arion8mo ago
Looks like the readonly fields are initialized first then the constructor If you do initialize a readonly field from the constructor, thats also do-able
Jimmacle
Jimmacle8mo ago
it would be prefered if you're using a field and not a property because they are different things for different kinds of members if you take the rule "don't expose fields publicly" and apply it here that answers your question
fæ
8mo ago
okay, readonly fields for class-wide manipulation
Accord
Accord8mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.