如何使用一个属性来初始化另一个属性?

问题描述 投票:0回答:4

这是为什么:

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

不可能吗?

因为手动操作:

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

有效,(显然?)这个:

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

有没有办法让第一个示例进行编译,还是我必须在构造函数中手动完成?

(我真正的问题要复杂得多,不仅仅是整数,还有随后用于创建其他实例的实例,但这个示例更容易讨论)

c# constructor properties roslyn c#-6.0
4个回答
6
投票

这是不可能的原因是这些初始化是在调用构造函数之前完成的。所以它发生在“静态”环境中。该对象尚未完全初始化,并且还没有 this 引用。因此您无法访问像 X

 这样的
非静态属性。
出于同样的原因,它适用于第三个示例中的 
static

属性。

所以我没有看到解决方法,而是在构造函数中进行这种初始化。

您不能在属性

2
投票
的初始值设定项表达式中使用非静态属性

Y

 的值,其原因与您不能在字段 
的初始值设定项表达式中使用非静态字段
x
的值相同y
,即
public int x = 5;
public int y = x; // Not allowed

这会触发
错误CS0236
,因为编译器可以决定处理部分类的字段和属性初始值设定项的顺序。虽然当两个属性都在同一文件中定义时,可以保证

XY

 之前初始化,但对于在包含分部类代码的不同文件中定义的属性,则没有这样的保证。
编译器设计者可以通过允许初始化程序引用在初始化字段或属性之前定义的其他字段和属性来以不同的方式实现它,但该功能不值得麻烦,因为您可以通过将初始化移动到构造函数中来轻松解决它。

在构造函数内执行相同操作不会出现问题,因为您可以控制赋值的顺序。当您在构造函数中指定

X

必须在

Y

 之前初始化时,编译器不允许更改该顺序。

这就是你要做的:

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

基于其他属性的自动属性的更好方法: 公共类测试类 { 公共 int X { 得到;放; } = 5; 公共整数 Y { 得到 { var y = X; 返回y; } } }
    

随着 C# 12 中主构造函数(类似于 F# 的主构造函数)的出现,现在这几乎成为可能。

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

如果您愿意公开一个额外的公共
TestClass(int x)
构造函数,那么效果很好。如果有一种方法可以使该构造函数

private

,这将提供
精确
您正在寻找的内容。
也许在未来的语言版本中,设计者也会允许这样做:他们在功能提案中特别承认了这种潜在的扩展(请参阅:

https://learn.microsoft.com/en-us/dotnet/csharp/language-参考/提案/csharp-12.0/primary-constructors#drawbacks;
特别是“缺点”部分中的最后一个要点)。

© www.soinside.com 2019 - 2024. All rights reserved.