我应该总是/永远/永远不会将对象字段初始化为默认值吗?

时间:2009-03-11 19:59:52

标签: language-agnostic coding-style

代码样式问题在这里。

我查看了this问题,询问.NET CLR是否真的总是初始化字段值。 (答案是。)但令我感到震惊的是,我不确定让它做到这一点总是一个好主意。我的想法是,如果我看到这样的声明:

int myBlorgleCount = 0;

我有一个非常好的想法,程序员希望计数从零开始,并且可以,至少在不久的将来。另一方面,如果我看到:

int myBlorgleCount;

如果0是合法或合理的值,我没有真正的直接想法。如果程序员刚刚开始阅读和修改它,我不知道程序员是否打算在设置值之前开始使用它,或者他们是否期望它为零等等。

另一方面,一些相当聪明的人和Visual Studio代码清理实用程序告诉我删除这些冗余声明。对此有何普遍共识? (有共识吗?)

我将此标记为语言不可知,但是如果有一个奇怪的情况,那么特别好的想法是针对特定语言的反对,那可能值得指出。

编辑:虽然我确实认为这个问题与语言无关,但它显然不适用于像C这样没有进行值初始化的语言。

编辑:我很感谢John的回答,但这正是我正在寻找的。我知道.NET(或Java或其他)将完成这项工作并一致且正确地初始化值。我所说的是,如果我看到代码修改了之前未在代码中明确设置的值,我作为代码维护者,不知道原始编码器是否意味着它是默认值,或者只是忘记设置值,或者期望将其设置在其他地方等等。

17 个答案:

答案 0 :(得分:24)

考虑长期维护。

  • 尽可能明确地保持代码。
  • 如果您不需要,请不要依赖语言特定的方式进行初始化。也许这种语言的新版本会以不同的方式工作?
  • 未来的程序员会感谢你。
  • 管理层会感谢你。
  • 为什么甚至一点点混淆了什么呢?

更新:未来的维护者可能来自不同的背景。这真的不是什么是“正确”,而是从长远来看更容易实现的目标。

答案 1 :(得分:13)

您始终可以安全地假设平台以平台的工作方式运行。 .NET平台将所有字段初始化为默认值。如果您看到一个未被代码初始化的字段,则表示该字段由CLR初始化,而不是未初始化。

此问题对于不保证初始化但不保证初始化的平台有效。在.NET中,更经常表示开发人员的无知,认为初始化是必要的。


过去的另一个不必要的遗留问题如下:

string foo = null;
foo = MethodCall();

我从那些应该更了解的人那里看到了这一点。

答案 2 :(得分:4)

我认为如果它澄清了开发人员的意图,那么初始化值是有意义的。

在C#中,没有任何开销,因为无论如何都要初始化值。在C / C ++中,未初始化的值将包含垃圾/未知值(无论内存位置是什么),因此初始化更为重要。

答案 3 :(得分:4)

我认为应该这样做,如果它真的有助于使代码更容易理解。

但我认为这是所有语言功能的一般问题。我的意见是:如果它是该语言的官方功能,你可以使用它。(当然有一些反功能应谨慎使用或完全避免使用,如在Visual Basic中缺少option explicit或在C ++中缺少钻石继承)

有一段时间,我非常偏执,并添加了各种不必要的初始化,显式演员表,超级偏执的try-finally块,...我曾经想过忽略自动装箱并用显式类型替换所有出现的事件转换,只是“为了安全起见”。

问题是:没有结束。您可以避免几乎所有语言功能,因为您不想信任它们。

记住:在你理解之前,它才是唯一的魔力:)

答案 4 :(得分:2)

我同意你的意见;它可能很冗长,但我喜欢看:

int myBlorgleCount = 0;

现在,我总是初始化字符串:

string myString = string.Empty;

(我只讨厌空字符串。)

答案 5 :(得分:1)

我总是在构造函数中显式初始化字段。对我来说,这是做这件事的地方。

答案 6 :(得分:1)

根据我的经验,我发现显式初始化局部变量(在.NET中)会增加比清晰度更混乱。

另一方面,应该始终初始化类范围的变量。在过去,我们为公共变量类型定义了系统范围的自定义“null”值。通过这种方式,我们总能知道错误未初始化的内容以及故意初始化的内容。

答案 7 :(得分:1)

如果我无法立即将其设置为有用的东西

int myValue = SomeMethod();

我将它设置为0.这更是为了避免不得不考虑其他值。对我来说,整数总是设置为0的事实不在我的手指尖上,所以当我看到

int myValue;

我需要花一点时间才能了解这一事实,并记住它将会被设置为什么,从而扰乱我的思维过程。 对于那些知识渊博的人,他们会遇到

int myValue = 0;

并且想知道为什么那个人将它设置为零,当编译器只为他们做这件事时。这种想法会打断他们的思考过程。

所以对你和你工作的团队来说最有意义。如果通常的做法是设置它,那么设置它,否则不要。

答案 8 :(得分:0)

如果某个字段通常会将新值存储在其中,而不考虑之前的字段,并且该字段应该表现得好像最初存储了零,但是没有什么"特殊"大约为零,那么该值应该明确存储。

如果该字段代表一个永远不会直接写入非零值的计数或总数,而是总是要添加或减去其他金额,那么零应被视为"空"价值,因此无需明确说明。

使用粗略类比,请考虑以下两个条件:

  1. `if(xposition!= 0)...
  2. `if((flags& WoozleModes.deluxe)!= 0)...
  3. 在前一种情况下,与文字零的比较是有意义的,因为它正在检查一个在语义上与其他任何不同的位置。然而,在第二种情况下,我建议与字面零的比较不会增加可读性,因为代码并不真正感兴趣的是表达式(flags & WoozleModes.deluxe)的值恰好是零以外的数字,而是它是否"非空"。

    我不知道任何编程语言提供单独的方法来区分"零"并且"清空",除了在指示空虚时不要求使用字面零。

答案 9 :(得分:0)

我认为很多都归结为过去的经历。

在旧语言和非语言语言中,期望值是未知的。来自这些语言的程序员保留了这种期望。

几乎所有现代或托管语言都为最近创建的变量定义了值,无论是来自类构造函数还是语言功能。

现在,我认为初始化一个值是完全可以的;曾经隐含的内容变得明确。从长远来看,比如说,在接下来的10到20年里,人们可能会开始了解默认值是可能的,预期的和已知的 - 特别是如果它们在各种语言中保持一致(例如,字符串为空字符串,数字为0)

答案 10 :(得分:0)

答案 11 :(得分:0)

另一件需要记住的事情是,如果您要使用自动属性,则必须依赖隐含值,例如:

public int Count { get; set; }

答案 12 :(得分:0)

我不会初始化它们。如果您声明尽可能接近第一次使用,那么不应该有任何混淆。

答案 13 :(得分:0)

这被标记为与语言无关,但大多数答案都与C#有关。

在C和C ++中,最佳做法是始终初始化您的值。在某些情况下会为您完成此操作,例如静态全局变量,但是对于大多数编译器冗余初始化这些值,不应该有任何性能损失。

答案 14 :(得分:0)

我不会这样做。 C#无论如何都将int初始化为零,因此这两行在功能上是等价的。一个是更长和多余的,虽然对于不了解C#的程序员更具描述性。

答案 15 :(得分:0)

我通常是为字符串而做的,在某些情况下,我不希望空值浮动。 我工作的一般共识是“不要为值类型明确地做。”

答案 16 :(得分:0)

你应该这样做,没有必要,但如果这样做会更好,因为你永远不知道你使用的语言是否初始化了这些值。通过自己完成,您可以确保您的值都已初始化并且设置了标准预定义值。 这样做除了可能有点“浪费时间”之外没有任何问题。我强烈推荐它。虽然约翰的表扬非常有用,但在一般情况下,最好走安全路径​​。