谜题30: 循环者的爱子
请提供一个对i的声明,将下面的循环转变为一个无限循环:
while (i != i + 0)
{
}
与前一个谜题不同,你必须在答案中不使用浮点数。换句话说,你不能把i声明为double或float类型。
解惑30: 循环者的爱子
与前一个谜题一样,这个谜题初看起来是不可能实现的。毕竟,一个数字总是等于它自身加上0,你被禁止使用浮点数,因此不能使用NaN。而在整数类型中没有NaN的等价物。那么,你能给出什么呢?
我们必然可以得出这样的结论,即i的类型必须是非数值类型的,并且其中存在着解惑方案。唯一的+操作符有定义的非数值预定义类型就是string。+操作符被重载了:对于string类型,它执行的不是加法而是字符串连接。如果在连接中的某个操作数具有非string的类型,那么这个操作数就会在连接之前转换成字符串[C#语言规范 7.7.4]。
事实上,i可以被初始化为任何值,只要它是string类型即可,例如:
string i = "Buy seventeen copies of Effective Java!";
int类型的数值0被转换成string类型的数值"0"并且被追加到感叹号之后,所产生的字符串就不等于最初的字符串了,因此,计算布尔表达式(i != i + 0)得到的值就是true,循环也就永远不会终止了。
总之,操作符重载是很容易令人误解的。在本谜题中的加号看起来是表示一个加法,但是通过为变量i选择合适的类型,即string,我们让它执行了字符串连接操作。甚至因为变量被命名为i,使得本谜题更加容易令人误解,因为i通常被当作整型变量名而保留。对于程序的可读性来说,好的变量名、方法名和类名至少与好的注释同等重要。
对语言设计者的教训与谜题11和13中的教训相同。操作符重载很容易引起混乱,也许+操作符就不应该被重载用来进行字符串连接操作。有充分的理由证明提供一个字符串连接操作符是多么必要,但是它不应该是+。
C#解惑总目录