我最近正在使用一个DateTime对象,并写了这样的东西:

DateTime dt = DateTime.Now;
dt.AddDays(1);
return dt; // still today's date! WTF?

AddDays()的智能感知文档说它在日期后添加了一天,但它并没有这样做——它实际上返回了一个添加了一天的日期,所以你必须这样写:

DateTime dt = DateTime.Now;
dt = dt.AddDays(1);
return dt; // tomorrow's date

这个问题以前已经困扰过我很多次了,所以我认为将最糟糕的c#陷阱分类会很有用。


当前回答

可枚举对象可以计算不止一次

当您有一个惰性枚举的可枚举对象,并且对其进行两次迭代并得到不同的结果时,它会咬您一口。(或者你得到相同的结果,但它执行两次不必要的)

例如,在编写某个测试时,我需要一些临时文件来测试逻辑:

var files = Enumerable.Range(0, 5)
    .Select(i => Path.GetTempFileName());

foreach (var file in files)
    File.WriteAllText(file, "HELLO WORLD!");

/* ... many lines of codes later ... */

foreach (var file in files)
    File.Delete(file);

想象一下当file . delete (file)抛出FileNotFound时我的惊讶!!

这里发生的情况是,可枚举的文件被迭代了两次(第一次迭代的结果根本没有被记住),在每次新的迭代中,您将重新调用Path.GetTempFilename(),因此您将得到一组不同的临时文件名。

当然,解决方案是使用ToArray()或ToList()快速枚举值:

var files = Enumerable.Range(0, 5)
    .Select(i => Path.GetTempFileName())
    .ToArray();

当你在做一些多线程的事情时,这甚至更可怕,比如:

foreach (var file in files)
    content = content + File.ReadAllText(file);

你会发现内容。在所有写入之后,长度仍然为0 !!然后,当....时,您开始严格检查是否没有竞态条件浪费了一个小时之后……你发现这只是一个微小的可枚举的东西,你忘记了....

其他回答

mystring.Replace("x","y")

虽然它看起来应该对被调用的字符串进行替换,但实际上它返回了一个新字符串,替换完成后没有改变被调用的字符串。你需要记住字符串是不可变的。

在调试环境中求值时,base关键字不能按预期工作:方法调用仍然使用虚拟分派。

当我偶然发现它时,我浪费了很多时间,我以为我遇到了CLR时空中的某种裂缝,但我后来意识到这是一个已知的(甚至有点故意的)bug:

http://blogs.msdn.com/jmstall/archive/2006/06/29/funceval-does-virtual-dispatch.aspx

[Serializable]
class Hello
{
    readonly object accountsLock = new object();
}

//Do stuff to deserialize Hello with BinaryFormatter
//and now... accountsLock == null ;)

这个故事的寓意:反序列化对象时不运行字段初始化程序

我经常提醒自己DateTime是一个值类型,而不是引用类型。对我来说太奇怪了,特别是考虑到它的各种构造函数。

下面的代码不会捕获. net中的异常。相反,它会导致StackOverflow异常。

private void button1_Click( object sender, EventArgs e ) {
    try {
        CallMe(234);
    } catch (Exception ex) {
        label1.Text = ex.Message.ToString();
    }
}
private void CallMe( Int32 x ) {
    CallMe(x);
}

对于评论(和反对票): 如此明显的堆栈溢出是极其罕见的。但是,如果发生异常,您将不会捕获异常,并且可能会花费几个小时试图查找问题的确切位置。如果SO出现在很少使用的逻辑路径中,特别是在web应用程序中,你可能不知道引发问题的确切条件,那么情况就会更加复杂。

这与这个问题的公认答案完全相同(https://stackoverflow.com/a/241194/2424)。答案上的属性getter本质上做的事情与上面的代码完全相同,并且在没有堆栈跟踪的情况下崩溃。