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

时间:2023-01-07 21:28:42

This question is inspired by Jon Skeet's answer: Is there a c# equivalent to c++'s access-modifier regions

这个问题的灵感来自于Jon Skeet的回答:c#是否与c ++的访问修饰区相当

He makes a comment that it is possible for the order of fields in a file to matter. I am guessing that this has to do with the order that the fields are initialized, but I think it's a dangerous enough thing to code based on this side effect that it warranted its own question and discussion.

他发表评论说文件中字段的顺序可能很重要。我猜这与字段初始化的顺序有关,但我认为根据这种副作用进行编码是一件危险的事情,它保证了自己的问题和讨论。

Are there other thoughts around how the order of fields within your code file could be manipulated and what impact that might have?

是否有其他想法可以处理代码文件中的字段顺序以及可能产生的影响?

6 个解决方案

#1


Here is a classic example from the C# language spec (Section 10.5.5)

以下是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);
    }
}

This is a completely valid program and as written (a = 1, b =2). However if you swap the ordering of the fields they will also swap values.

这是一个完全有效的程序并且是书面的(a = 1,b = 2)。但是,如果您交换字段的顺序,它们也将交换值。

#2


Yeah, it does matter when interfacing with unmanaged code.

是的,在与非托管代码连接时确实很重要。

#3


I was primarily thinking about the order of initialization, yes - particularly for static fields. For instance (with public fields just for simplicity of demonstration):

我主要是考虑初始化的顺序,是的 - 特别是对于静态字段。例如(公共字段只是为了简化演示):

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);
    }
}

The order of initialization is defined in the spec to be the textual order in which the variables are declared - but it becomes undefined when two variables are in different files contributing to a partial class.

初始化顺序在规范中定义为声明变量的文本顺序 - 但是当两个变量位于不同的文件中时,它将变为未定义,从而导致部分类。

Mehrdad's answer is another good one: anything where physical layout is important will quite possibly be affected by declaration order.

Mehrdad的答案是另一个好的:物理布局很重要的任何事情很可能会受到声明顺序的影响。

#4


If fields are initialized as part of the declaration, they are added to the constructor (instance or static) in the order they appear in the file.

如果字段作为声明的一部分进行初始化,则它们将按照它们在文件中出现的顺序添加到构造函数(实例或静态)中。

#5


You can use (abuse?) the order of fields as metadata of your class which you can than read via reflection.

你可以使用(滥用?)字段的顺序作为你的类的元数据,你可以通过反射阅读。

for example, if you have a class that represents a network protocol with fields ID, PORT, and XOR, in that order, you could define it as:

例如,如果您有一个表示具有字段ID,PORT和XOR的网络协议的类,则可以按以下顺序将其定义为:

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

Now suppose you use reflection to iterate the fields of the protocol, to send over the wire. The order returned by GetProperties will be as you defined, and you didn't have to write any extra metadata explicitly.

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

Not sure if it's a good idea though to depend on this.

不确定这是否是一个好主意,但依赖于此。

#6


I believe XmlSerializer serializes members in the order they appear in the source file.

我相信XmlSerializer按照它们在源文件中出现的顺序序列化成员。

#1


Here is a classic example from the C# language spec (Section 10.5.5)

以下是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);
    }
}

This is a completely valid program and as written (a = 1, b =2). However if you swap the ordering of the fields they will also swap values.

这是一个完全有效的程序并且是书面的(a = 1,b = 2)。但是,如果您交换字段的顺序,它们也将交换值。

#2


Yeah, it does matter when interfacing with unmanaged code.

是的,在与非托管代码连接时确实很重要。

#3


I was primarily thinking about the order of initialization, yes - particularly for static fields. For instance (with public fields just for simplicity of demonstration):

我主要是考虑初始化的顺序,是的 - 特别是对于静态字段。例如(公共字段只是为了简化演示):

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);
    }
}

The order of initialization is defined in the spec to be the textual order in which the variables are declared - but it becomes undefined when two variables are in different files contributing to a partial class.

初始化顺序在规范中定义为声明变量的文本顺序 - 但是当两个变量位于不同的文件中时,它将变为未定义,从而导致部分类。

Mehrdad's answer is another good one: anything where physical layout is important will quite possibly be affected by declaration order.

Mehrdad的答案是另一个好的:物理布局很重要的任何事情很可能会受到声明顺序的影响。

#4


If fields are initialized as part of the declaration, they are added to the constructor (instance or static) in the order they appear in the file.

如果字段作为声明的一部分进行初始化,则它们将按照它们在文件中出现的顺序添加到构造函数(实例或静态)中。

#5


You can use (abuse?) the order of fields as metadata of your class which you can than read via reflection.

你可以使用(滥用?)字段的顺序作为你的类的元数据,你可以通过反射阅读。

for example, if you have a class that represents a network protocol with fields ID, PORT, and XOR, in that order, you could define it as:

例如,如果您有一个表示具有字段ID,PORT和XOR的网络协议的类,则可以按以下顺序将其定义为:

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

Now suppose you use reflection to iterate the fields of the protocol, to send over the wire. The order returned by GetProperties will be as you defined, and you didn't have to write any extra metadata explicitly.

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

Not sure if it's a good idea though to depend on this.

不确定这是否是一个好主意,但依赖于此。

#6


I believe XmlSerializer serializes members in the order they appear in the source file.

我相信XmlSerializer按照它们在源文件中出现的顺序序列化成员。