【问题标题】:How do I use a property to initialize another property?如何使用一个属性来初始化另一个属性?
【发布时间】:2016-10-17 22:16:30
【问题描述】:

为什么会这样:

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;

有没有办法让第一个示例编译,还是我必须在 ctor 中手动完成?

(我真正的问题要复杂得多,不仅仅是 int,还有实例会被用来创建其他实例,但这个例子更容易讨论)

【问题讨论】:

  • “因为这就是 C# 规范所说的”是不幸的答案“......在变量初始化程序中引用 this 是一个编译时错误,因为它是一个编译时错误变量初始化器通过简单名称引用任何实例成员"
  • @Damien_The_Unbeliever 谢谢,简单的名字是什么?
  • 一个简单的名字基本上是指一个成员,在它之前没有明确地写this.。例如。您在第一个示例的第二行中使用了一个简单的名称来引用 X 成员。
  • 它是否必须是由字段支持的只读属性?有人可能会争辩说 Y 可以定义为只返回 X 的值。您不一定需要存储空间。

标签: c# constructor properties roslyn c#-6.0


【解决方案1】:

这不可能的原因是这些初始化是在构造函数被调用之前完成的。。所以它发生在 静态 上下文中。该对象尚未完全初始化,还没有this 引用。所以你不能访问像X这样的非静态属性。

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

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

【讨论】:

  • “这些初始化是在调用构造函数之前完成的” 不正确。据我所知,它们已包含在构造函数中。
  • @PatrickHofman 它们在构造函数逻辑中的所有其他内容之前完成。构造对象的第一件事就是为对象预留内存,然后初始化,然后执行构造器逻辑。
  • @PatrickHofman 我猜你对编译器生成的代码是正确的,但从开发人员的角度来看,它是 before 构造函数,至少在 this 之前是可用,但 this 可以在构造函数中访问。
  • “在其他任何事情之前”与@Adwaenyth 的其他方法没有太大区别
  • @Mafi 对不起,误解了第二个例子,把它当作对象初始化器。
【解决方案2】:

您不能在属性 Y 的初始化表达式中使用非静态属性 X 的值,原因与您不能在初始化表达式中使用非静态字段 x 的值相同字段y,即

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

这会触发error CS0236,因为允许编译器决定它处理部分类的字段和属性初始值设定项的顺序。虽然当两个属性都在同一个文件中定义时,X 保证在 Y 之前初始化,但对于包含部分类代码的不同文件中定义的属性,没有这样的保证。

编译器设计者可以通过允许初始化程序引用在初始化字段或属性之前定义的其他字段和属性来以不同的方式实现它,但是该功能不值得麻烦,因为您可以通过将初始化移动到构造函数来轻松解决它。

在构造函数中做同样的事情不会出现问题,因为你可以控制赋值的顺序。当你在构造函数中说X必须在Y之前初始化时,编译器是不允许改变这个顺序的。

【讨论】:

  • 确实如此。我认为唯一真正的原因是执行顺序。当您手动编写构造函数时,您可以强制何时调用。如果我们让编译器或 CLR 这样做,我们可能会得到意外和不确定的行为。
  • "编译器被允许改变它处理字段和属性初始化器的顺序" - 不,它不是。根据 C# 规范,它们是按文本顺序处理的。
  • (C# 规范,第 5 版,第 10.5.5.2 节):“变量初始化程序按照它们在类声明中出现的文本顺序执行。”
  • 但是可以调用尚未初始化的变量。这可能会导致问题。如果你不允许这样做,你就“修复”了这个问题。
  • (回复:您对部分类的编辑。虽然我确实在 C# 规范中找不到关于如何为部分类定义文本顺序的规则,但基于快速阅读,它应该是注意到这个禁令早于部分类)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-26
  • 2020-12-01
  • 2012-10-05
  • 1970-01-01
相关资源
最近更新 更多