3

我是 C# 编程的新手。请帮我。

我创建了一个类Tester

class Tester 
{
    public int a = 5;
    public int b = a;
}

问题 1:为什么我不能使用这个变量a来初始化变量b

问题 2:如果我将变量更改为静态,那么它工作正常。为什么有区别?

class Tester
{
    public static int a = 5;
    public static int b = a;
}

问题 3:在前面的示例中,如果我交换变量序列,那么它工作正常,为什么因为a声明 after b。它如何初始化a

class Tester
{
    public static int b = a; // 0
    public static int a = 5; // 5
}
4

3 回答 3

3

当您使用字段初始化器时,会出现一些棘手的初始化顺序问题。一个简单的例子是:

class Test {
   int a = b;
   int b;
   public Test() {
      b = 1;
   }
}

的价值是a多少?如果您使用 constructor-initializes-object 规则,那么a将是 1。但它不是在后台工作的方式,a如果语法有效,则为 0。字段初始值设定项实现方式的副作用,它们的代码在构造函数主体中的代码之前被注入构造函数。当类继承具有构造函数的基类时,这个问题变得更加复杂。

这太丑陋了,C#语言设计者通过简单地禁止这种代码来解决这个问题。规则是您不能在字段初始值设定项中引用this,这将创建对其类构造函数尚未完成执行的对象的引用。

静态字段的规则放宽了,没有this引用,CLR 为类初始化程序的执行顺序提供了不错的保证。然而,这并不能避免歧义,在这个例子中猜测字段值是什么是一个练习:

class Test {
    static int a = b + 1;
    static int b = a + 1;
}

试一试,看看你是否能理解结果。否则它是明确定义的。

于 2013-10-14T10:16:37.907 回答
2

答1:您不能使用一个实例变量来初始化另一个实例变量。为什么?因为编译器可以重新排列这些 - 不能保证变量“a”将在“b”之前初始化,所以上面的行可能会抛出 NullReferenceException。

回答 2:它适用于静态,因为静态在其他变量之前初始化并且它们的引用没有改变。

如果有帮助,请告诉我。

于 2013-10-14T09:46:11.213 回答
1

正如阿尼鲁德所说。您不能使用实例变量来初始化另一个实例变量。为什么?因为编译器可以重新排列这些——不能保证a之前会被初始化b

您可以为此使用构造函数。

class Tester
{
   public int a=5;
   public int b;
   public Tester()//constructor
   {
      b=a;
   }
}

或者

class Tester
{
    public static int a = 5;
    public static int b;
    public Tester()//constructor
    {
        b = a;
    }
}
于 2013-10-14T10:08:24.620 回答