我在一些具有以下常量的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";
答案 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”?
答案 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)
答案 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_EQUAL
是string.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)
我可以考虑使用常量的四个原因:
IdColumnNumber = 1
)。FirstAsciiLetter = 65
),LongSongTitle = "Supercalifragilisticexpialidocious"
)PI = 3.14159265
)对于您的具体示例,以下是我对每个示例的判断:
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 = 0
或A = "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的常量是没有意义的,浪费手指能量!