不断滥用?

时间:2009-12-07 20:15:36

标签: c# coding-style

我在一些具有以下常量的C#项目中遇到过一堆代码:

    const int ZERO_RECORDS = 0;
    const int FIRST_ROW = 0;
    const int DEFAULT_INDEX = 0;
    const int STRINGS_ARE_EQUAL = 0;

有没有人见过这样的东西?有没有办法合理化使用常量来表示语言结构? IE:C#在数组中的第一个索引位于第0位。我认为如果开发人员需要依赖常量来告诉他们语言是0,那么就会出现更大的问题。

这些常量的最常见用法是处理数据表或“for”循环。

我是不是觉得这些是代码味道?我觉得这些并不比以前好多了:

const int ZERO = 0;
const string A = "A";

17 个答案:

答案 0 :(得分:12)

  

我是不是觉得这些是代码味道?我觉得这些并不比以前好多了:

比较以下内容:

if(str1.CompareTo(str2) == STRINGS_ARE_EQUAL) ...

if(str1.CompareTo(str2) == ZERO) ...
if(str1.CompareTo(str2) == 0) ...

哪一个更直接有意义?

答案 1 :(得分:10)

滥用,恕我直言。 “零”只是其中的基础之一。

虽然STRINGS_ARE_EQUAL可能很简单,但为什么不“.Equals”?

Accepted limited use of magic numbers?

答案 2 :(得分:5)

有些人认为程序中的任何原始数字都是“神奇数字”。我已经看到编码标准基本上说你不能只是把一个整数写入程序,它必须是一个const int。

答案 3 :(得分:5)

这绝对是代码味道。

意图可能是为代码添加“可读性”,但是在我看来这样的事情实际上会降低代码的可读性。

答案 4 :(得分:3)

  

我是不是觉得这些是代码味道?我觉得这些并不比以前好多了:

     

const int ZERO = 0;

     

const int A ='A';

可能有点嗅觉,但肯定比ZERO = 0和A ='A'好。在第一种情况下,他们定义了逻辑常量,即一些具有实现价值实现的抽象概念(字符串相等)。

在您的示例中,您定义了文字常量 - 变量表示值本身。如果是这种情况,我认为枚举是首选,因为它们很少是奇异值。

答案 5 :(得分:3)

这是明确的错误编码。

我说常量应该只在需要的地方使用,以便以后可能发生变化。例如,我有许多“配置”选项,如SESSION_TIMEOUT定义它应该保持不变,但也许它可以在以后调整。我不认为ZERO可以在路上调整。

此外,对于幻数,不应包括零。

我对这个信念感到有点奇怪,因为我会说这样的事情会很远

//input is FIELD_xxx where xxx is a number
input.SubString(LENGTH_OF_FIELD_NAME); //cut out the FIELD_ to give us the number

答案 6 :(得分:2)

您应该查看thedailywtf

上的一些内容

One2Pt20462262185th

Enterprise SQL

答案 7 :(得分:2)

我认为有时人们盲目地遵循'编码标准',其中说“不要使用硬编码值,将它们定义为常量,以便在需要更新代码时更容易管理代码” - 对于像以下这样的东西来说这是公平的。

const in MAX_NUMBER_OF_ELEMENTS_I_WILL_ALLOW = 100

但是没有意义:

if(str1.CompareTo(str2) == STRINGS_ARE_EQUAL)

因为每当我看到此代码时,我都需要搜索STRINGS_ARE_EQUAL被定义为的内容,然后检查文档是否正确。

相反,如果我看到:

if(str1.CompareTo(str2) == 0)

我跳过第1步(搜索定义为STRINGS_ARE...的内容),并可以查看规范0的含义。

如果你只对一个案例感兴趣,例如:

,你会正确地想用Equals()替换它并使用CompareTo()
switch (bla.CompareTo(bla1))
{
     case IS_EQUAL:
     case IS_SMALLER:
     case IS_BIGGER:
     default:
}

如果合适,使用if/else语句(不知道CompareTo()返回什么......)

我仍然会检查你是否根据规格正确定义了值。

如果规范定义类似ComparisonClass::StringsAreEqual的值或类似的东西(我刚才那个),那么这当然是不同的,那么你就不会使用0而是适当的变量。

所以这取决于,当您特别需要访问数组arr[0]中的第一个元素时,优于arr[FIRST_ELEMENT],因为我仍然会检查您定义为FIRST_ELEMENT的内容,因为我会不信任你,它可能与0不同 - 例如你的0元素是dud,真正的第一个元素存储在1 - 谁知道。

答案 8 :(得分:1)

我会寻找代码味道。如果需要这些常量,请将它们放在枚举中:

enum StringEquality
{
    Equal,
    NotEqual
}

(但我怀疑STRINGS_ARE_EQUALstring.Compare返回的内容,因此黑客返回枚举可能会更加冗长。)

修改SHOUTING_CASE也不是特别.NET-style naming convention

答案 9 :(得分:1)

我不知道我是否会称它们为气味,但它们看起来似乎是多余的。虽然DEFAULT_INDEX实际上可能有用。

重点是避免幻数,而零并不是真正的神奇。

答案 10 :(得分:1)

这个代码是你办公室里的东西还是你下载的东西?

如果它在办公室,我认为如果人们随机放置常数,这就是管理问题。在全球范围内,除非每个人都清楚地了解或同意这些常数的用途,否则不应该有任何常数。

在C#中,理想情况下,您需要创建一个包含每个其他类全局使用的常量的类。例如,

class MathConstants
{
 public const int ZERO=0;
}

然后在以后的课程中,例如:

....
if(something==MathConstants.ZERO)
...

至少我是这样看的。这样每个人都可以理解那些常数甚至没有阅读其他内容。这会减少混乱。

答案 11 :(得分:1)

我可以考虑使用常量的四个原因:

  1. 替代未来可能发生合理变化的价值(例如IdColumnNumber = 1)。
  2. 作为价值的标签,可能不易理解或有意义(例如FirstAsciiLetter = 65),
  3. 作为输入冗长或难以输入值的较短且不易出错的方式(例如,LongSongTitle = "Supercalifragilisticexpialidocious"
  4. 作为难以记住的值的记忆辅助(例如,PI = 3.14159265
  5. 对于您的具体示例,以下是我对每个示例的判断:

    const int ZERO_RECORDS = 0;
    // almost definitely a code smell
    
    const int FIRST_ROW = 0;
    // first row could be 1 or 0, so this potentially fits reason #2,
    // however, doesn't make much sense for standard .NET collections
    // because they are always zero-based
    
    const int DEFAULT_INDEX = 0;
    // this fits reason #2, possibly #1
    
    const int STRINGS_ARE_EQUAL = 0;
    // this very nicely fits reason #2, possibly #4
    // (at least for anyone not intimately familiar with string.CompareTo())
    

    所以,我会说,不,这些并不比Zero = 0A = "A"差。

答案 12 :(得分:0)

使用常量来表示抽象值是可以的,但用你自己的语言表示构造则是另一种。

const int FIRST_ROW = 0没有意义。

const int MINIMUM_WIDGET_COUNT = 0更有意义。

您应遵循编码标准的假设是有道理的。 (也就是说,编码标准在组织内是推定正确的。)在不符合推定时严格遵循编码标准是没有意义的。

所以我同意早些时候的海报,一些臭味的常数可能是因为遵循编码标准(“没有魔法数字”)而毫无例外。这就是问题所在。

答案 13 :(得分:0)

在跨平台的情况下,您可能会看到类似这样的内容,您可以将该文件与适合该平台的常量集一起使用。但可能不是这些实际例子。这看起来像COBOL编码器试图使他的C#看起来更像英语(对于COBOL编码器没有违法行为)。

答案 14 :(得分:0)

对,你要问这个气味年轻的代码战士。但是,这些命名常量来自于比Visual Studio更早出现的编码实践。它们可能是多余的,但你可能比理解公约的起源更糟糕。想想美国宇航局的计算机,回想起来......

答案 15 :(得分:0)

闻到一点,但我可以看到这样的情况,特别是如果你有程序员一直从语言切换到语言。

例如,MATLAB是单索引的,所以我可以想象有人厌倦了在切换语言时犯下一个错误,并在C ++和MATLAB程序中定义DEFAULT_INDEX来抽象差异。不一定优雅,但如果这是它需要...

答案 16 :(得分:0)

如果零表示零以外的东西(在这种情况下为STRINGS_ARE_EQUAL)那么那就是神奇的。为它创建一个常量是可以接受的,并使代码更具可读性。

创建一个名为ZERO的常量是没有意义的,浪费手指能量!