C#中字段的顺序是否重要?

5
这个问题的灵感来自Jon Skeet的回答:Is there a c# equivalent to c++'s access-modifier regions
他评论说,文件中字段的顺序可能很重要。我猜这与初始化字段的顺序有关,但我认为基于这种副作用编写代码是一件危险的事情,值得单独讨论和探讨。
还有其他想法吗?在您的代码文件中调整字段的顺序可能会产生什么影响?

jon-skeet 在 SO 上有一个标签?这有必要吗?我认为每个问题都有一个默认标签。 ;) - Mehrdad Afshari
他有一个标签,这不是我创建的...我认为它在那里,为什么不使用它,但如果大家想要的话,我会将其删除。 - JoshBerke
6个回答

27

这是C#语言规范(第10.5.5节)中的经典示例。

class Test
{
    static int a = b + 1;
    static int b = a + 1;
    static void Main() {
        Console.WriteLine("a = {0}, b = {1}", a, b);
    }
}

这是一个完全有效的程序,就如它写的一样(a = 1, b = 2)。但是如果你交换字段的顺序,它们也会交换值。


1
我很惊讶这个编译通过了 - 我本来以为编译器会检测到使用未初始化的字段(而我的更复杂的例子则更难发现)。这是一个漂亮简洁的演示。 - Jon Skeet
有趣的是,在Java中它不会出现这种情况。 - Jon Skeet
@Jon,我第一次看到这个例子时也感到非常惊讶。 - JaredPar
@Jon:字段从未被初始化过,只有本地变量(和out参数)会被初始化。字段(静态或其他)总是默认初始化的。实际上,这意味着在运行初始化程序和构造函数之前,包含字段的整个内存区域都被清零。 - P Daddy
这就是为什么结构体不能有实例字段初始化器的原因。这会破坏零值默认初始化行为。 - P Daddy
很好的例子 - 让我感到惊喜。 - HTTP 410

3

是的,在与非托管代码进行接口交互时很重要。


1
好的,是的,我知道,但是我忘了,不是也有一个LayoutKind属性吗?可以告诉编译器按特定顺序组织字段。 - JoshBerke
@Josh,有的,但是按正确顺序声明它们会更容易。 - JaredPar

2

我主要考虑的是初始化的顺序,特别是对于静态字段。例如(为了演示简单起见,这里使用公共字段):

using System;

class First
{
    static int a = 10;
    public static int b = CalculateB();
    static int c = 5;

    static int CalculateB()
    {
        return a*c;
    }
}

class Second
{
    static int a = 10;
    static int c = 5;
    public static int b = CalculateB();

    static int CalculateB()
    {
        return a*c;       
    }
}

class Test
{
    static void Main()
    {
        Console.WriteLine("First.b: {0}, Second.b: {1}",
                          First.b, Second.b);
    }
}

初始化顺序在规范中被定义为变量声明的文本顺序 - 但当两个变量位于不同的文件中,贡献到部分类时,它变得未定义。

Mehrdad的答案也很好:任何需要物理布局的东西都很可能会受到声明顺序的影响。


感谢您对评论的进一步解释;-) 这正是我想到的,只是无法表达得那么好。 - JoshBerke

1
如果字段在声明时初始化,它们将按照它们在文件中出现的顺序添加到构造函数(实例或静态)中。

0

我相信XmlSerializer按照源文件中的顺序对成员进行序列化。


0

你可以利用字段的顺序作为类的元数据,然后通过反射读取。

例如,如果你有一个表示网络协议的类,它的字段顺序是ID、PORT和XOR,你可以这样定义:

class MyProtocol {
    int ID;
    int PORT;
    int XOR;
}

现在假设您使用反射来迭代协议的字段,以便通过网络发送。 GetProperties 返回的顺序将与您定义的顺序相同,而且您不必显式编写任何额外的元数据。

不确定依赖此功能是否是一个好主意。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接