【问题标题】:Definition/Initialization of Global Variables: Common Practice? (Geared towards C#)全局变量的定义/初始化:常见做法? (面向 C#)
【发布时间】:2010-09-09 12:37:38
【问题描述】:

几天前我发布了一个类似的问题,但它更适合任何 *.Designer.cs 文件。这个问题面向类中全局变量的声明和初始化。据我所知,将所有全局变量放在类定义的开头,然后以任意顺序放置其余代码(我更喜欢 Getters 和 Setters,然后是构造函数,然后是事件,然后是杂项函数)。好吧,我已经看到它完成了,并且我自己在声明时设置了全局变量的地方完成了它。

我不是指:

ClassA clA = new ClassA();

我指的是:

private int nViewMode = (int)Constants.ViewMode.Default;

现在,我听到人们说并且我在某些层面上同意它,即这些变量的初始化,那些在声明变量时不需要new 语句的变量,应该在构造函数或初始化函数。然而,当他们这么说时,他们可能意味着前面的陈述很好,但不是下面的:

走错路

private int nTotal = 100;
private int nCount = 10;
private int nDifference = nTotal - nCount;

可能的正确方法

private int nTotal = 100;
private int nCount = 10;
private int nDifference = 0;

void ClassConstructor()
{
  nDifference = nTotal - nCount;
}

我的问题是:

在这种情况下,最常见/标准的做法是什么? 两者的优缺点是什么? 这些问题是否仅与某些语言相关而不与其他语言相关?

我在打字时想到的最后一个问题,这就是原因。在 Visual Studio 2008 中,我似乎可以在全局变量声明上放置断点,而我认为我在大学时曾经编写 C++ 时不能。另外,我相信在大学里,你不能使用在当前变量之前立即声明的变量,但话又说回来,那是在 C++ 中。所以我不确定这些问题是否只适用于 MSVS 产品(我们在大学里使用过 Borland)、较新的编译器,或者其他什么不适用。如果有人有任何见解,不胜感激。谢谢。

【问题讨论】:

  • 那不是全局变量,只是普通的成员变量。另外,我不会写private int nDifference = 0;,我只会写private int nDifference;,因为不需要= 0
  • 恕我直言,至于变量声明。仅在构造函数中声明字段并设置其值。为了获得更好的代码,我建议只在原地声明 const。它带来了简单的代码顺序和可理解性
  • 在声明中初始化值与在构造函数中初始化相同——编译器可以做到这一点。我在构造函数中看到的唯一优点是,如果重要的话,您可以以显式的初始化顺序(在其他代码之前/之后)进行控制。
  • @ho1 - 我放 = 0 的原因是因为对于某些语言/编译器,我记得如果你没有将整数初始化为一个值,它可以给出内存中的任何内容,这可能是 -143255346363 或任何情况。而且我可能错了,但我一直认为成员变量是全局变量,因为它们用于该类的每个函数。但是,如果当我说全局时,每个人都想到了整个项目中使用的变量,我很抱歉。
  • @ILya - 是的,我也是这么想的。我想获得“程序员社区”的意见,这样当/如果我换工作时,我看起来就不会像个傻瓜。 :) 谢谢。

标签: c# initialization global-variables declaration


【解决方案1】:

我相信这个问题之前已经讨论过很多次了,但实际上没有其他答案:无论你最终做了什么,确保它与你项目中其他地方的代码保持一致。

个人更喜欢在构造函数之外初始化默认值,除非它们的计算基于使用的构造函数不同。这样,如果出现另一个构造函数,就不需要重复初始化代码了。

在 nDifference 的情况下,封装逻辑的 Property 可能更有意义:

  1. 如果不使用,则不需要在每次创建类的新实例时计算 nDifference。
  2. 它表示无论使用哪个构造函数,nDifference 的逻辑都应始终相同。

【讨论】:

  • 是的,我就是这么想的。对于不同的构造函数,我认为唯一合适的是默认值而不是计算值。而且我认为它已被问过几次,但不必找到一个以与我相同的方式提出问题的人,我认为最好发布我自己的问题。感谢您的回复。
【解决方案2】:

C# 语言定义保证字段初始化将在每个编译单元(文件)内按文本顺序进行。这意味着在静态字段声明的变量初始化器中包含复杂的表达式是完全可以的。 (另一方面,实例字段不能引用其他实例字段。)

如果字段的初始值取决于先前的值,那么它们可能应该保持在一起以避免意外重新排序。

class Demo1 {
    static int x = y + 10;  // x == 10
    static int y = 5;
}

class Demo2 {
    static int y = 5;
    static int x = y + 10;  // x == 15
}

正如其他人所说,我希望在声明中出现所有实例通用的初始化程序(无论选择的构造函数如何)。

这种重新排序行为仅适用于静态变量初始值设定项。常量初始化发生在编译时,并按照确保正确初始化值的顺序计算值(与变量不同,常量的循环引用是不允许的)。

class Demo3 {
    const int x = y + 10;  // Evaluated second. x == 15
    const int y = 5;       // Evaluated first.
}

您应该真正考虑是否需要存储计算值,因为在许多情况下,它可以在使用时计算。

class Demo4 {
    int y = 5;
    int x { get { return y + 10; } }
}

【讨论】:

  • 非常感谢。这让很多事情都变得清晰起来。相信我,我经常滥用 getter 和 setter。很高兴知道事情是有秩序的。我可能不得不去const 我所有的变量。 :)
  • 您的 Demo1 和 Demo2 示例无效:这些会产生编译错误。如果您将它们设为静态,它们将是有效的。
【解决方案3】:

就个人而言,我喜欢能够在 C# 中声明成员变量的地方初始化它们,特别是如果您要编写显式构造函数的唯一原因是初始化它们。

在较旧的 C# 方言中(我工作的地方仍然是 2.0),我想如果您在构造函数中填充成员 Dictionary<T> 或其他内容,则存在一致性参数,因为新的初始化程序语法没有显示直到后来。在这种情况下,您可以提出您希望将所有初始化放在一起的论点。同样,如果您基于构造函数参数初始化一些成员,则将所有初始化放在一起可能更有意义,而不是在构造函数中分配一些声明它的东西和其他东西 - 但是如果您有多个构造函数,如果您不会重复自己,您最终只会在一个地方进行一些初始化,而其余的则在另一个地方进行,因此您最好在声明它们的地方分配东西。

【讨论】:

  • 是的,我认为可能存在某些情况必须是一种方式而不是另一种方式。这就是我问这个问题的原因之一。如果与在声明时相比,必须在构造函数中初始化某些内容的问题实例更多,那么这将使其变得更加棘手。如果它只是将 int 初始化为 MAX 数或 MIN 数,那是一回事。但是将它们初始化为公式等,这可能会有点失控。不过谢谢你的意见。
【解决方案4】:

我更喜欢在构造函数中初始化所有字段,而不是在声明点。 (我对此做的唯一例外是静态字段,我发现添加静态构造函数过大了。)我的原因是我喜欢将所有构造逻辑放在一个地方,其次是为了避免调试器在单步执行代码。但是,这只是我的偏好,您可以随意提出您最喜欢的任何约定。

正如其他人已经说过的那样,请仔细考虑您的约定并始终如一地应用它。

【讨论】:

  • 是的,调试时我什至没有考虑到这一点。我想我什至见过人们声明一个成员变量并用函数的返回对其进行初始化。对我来说,这似乎是“意大利面条式”。感谢您的意见和见解。
猜你喜欢
  • 2020-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多