Mafii
Mafii

Reputation: 7425

How do I use a property to initialize another property?

Why is this:

public int X { get; } = 5
public int Y { get; } = X;

not possible?

Because doing it manually:

public TestClass()
{
  X = 5;
  Y = X;
}

Works, and so does (obviously?) this:

public static int X { get; } = 5;
public static int Y { get; } = X;

Is there a way to get the first example to compile, or do I have to do it manually in the ctor?

(My real problem is far more complex, not just ints, but instances that are then being used to create other instances, but this example is easier to discuss)

Upvotes: 2

Views: 2996

Answers (4)

Jwosty
Jwosty

Reputation: 3624

This is mostly possible now with the advent of primary constructors in C# 12 (which are similar to F#'s primary constructors).

public class TestClass(int x)
{
    public int X { get; } = x;
    public int Y { get; } = x;
    
    public TestClass() : this(5) { }
}

This works out great, provided that you're okay with exposing an additional public TestClass(int x) constructor. If there were a way to make that constructor private, this would provide precisely what you're looking for.


Perhaps in a future language version, the designers will allow this, too: they specifically acknowledges this potential extension in the feature proposal (see: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-12.0/primary-constructors#drawbacks; specifically the last bullet point in the "Drawbacks" section).

Upvotes: -1

Vinzan
Vinzan

Reputation: 1

This is how you would do it:

public class TestClass
{
    public int X { get; set; } = 5;
    public int Y => X;
}

Better way for auto properties based of other properties: public class TestClass { public int X { get; set; } = 5; public int Y { get { var y = X; return y; } } }

Upvotes: 0

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726469

You cannot use the value of a non-static property X in an initializer expression of property Y for the same reason that you cannot use the value of a non-static field x in an initializer expression of field y, i.e.

public int x = 5;
public int y = x; // Not allowed

This triggers error CS0236, because compiler is allowed to decide on the order in which it processes field and property initializers for partial classes. Although X is guaranteed to be initialized ahead of Y when both properties are defined in the same file, there is no such guarantee for properties defined in different files containing the code of a partial class.

Compiler designers could implement it differently by allowing initializers to reference other fields and properties defined before the field or property being initialized, but the feature is not worth the trouble, because you can easily work around it by moving intialization into the constructor.

Doing the same inside a constructor does not present a problem, because you are in control of the order of assignments. When you say in the constructor that X must be initialized before Y, the compiler is not allowed to change that order.

Upvotes: 2

René Vogt
René Vogt

Reputation: 43876

The reason why this is not possible is that these initializations are done before the constructor is called. So it happens in a static context. The object is not yet fully initialized and there is no this reference yet. So you cannot access a non-static property like X.

For the same reason it works for the static properties in your third example.

So I don't see a workaround but doing this kind of initialization in a constructor.

Upvotes: 7

Related Questions