【问题标题】:Does the order of fields in C# matter?C# 中字段的顺序是否重要?
【发布时间】:2009-01-10 16:06:25
【问题描述】:

这个问题的灵感来自 Jon Skeet 的回答: Is there a c# equivalent to c++'s access-modifier regions

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

关于如何操纵代码文件中的字段顺序以及可能产生什么影响,是否还有其他想法?

【问题讨论】:

  • jon-skeet 在 SO 上有一个标签?!有需要吗?我认为每个问题都有一个默认标签。 ;)
  • 他有一个我没有创建的标签....有点想它就在那里,所以为什么不使用它,但如果人们愿意,我会删除它。

标签: c# field specifications


【解决方案1】:

这是 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)。但是,如果您交换字段的顺序,它们也会交换值。

【讨论】:

  • 我对这个编译感到惊讶——我希望编译器能够检测到初始化字段的使用(而我的更复杂的示例更难发现)。这是一个简洁的演示。
  • 有趣的是,Java 中没有。
  • @Jon,我第一次看到这个例子时也很惊讶。
  • @Jon:字段永远不会未初始化,只有局部变量(和输出参数)。字段(静态或其他)始终默认初始化。在实践中,这意味着包含字段的整个内存区域在运行初始化程序和构造函数之前被清零。
  • ... 这就是为什么结构不能有实例字段初始值设定项的原因。它会破坏从零到默认初始化的行为。
【解决方案2】:

是的,与非托管代码交互时确实很重要。

【讨论】:

  • 好吧,是的,我知道,但我没想到是不是也有 LayoutKind 属性……告诉编译器按特定顺序组织字段。
  • @Josh,有但是以正确的顺序声明它们要容易得多
【解决方案3】:

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

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's answer 是另一个好方法:物理布局很重要的任何东西都很可能会受到声明顺序的影响。

【讨论】:

  • 感谢您扩展您的评论;-) 这就是我认为无法表达得这么好。
【解决方案4】:

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

【讨论】:

    【解决方案5】:

    您可以使用(滥用?)字段顺序作为类的元数据,而不是通过反射读取。

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

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

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

    不确定依赖这个是否是个好主意。

    【讨论】:

      【解决方案6】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-09-15
        • 2014-08-10
        • 2013-10-31
        • 1970-01-01
        • 2019-12-11
        • 2010-11-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多