我最近正在使用一个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#陷阱分类会很有用。


当前回答

当可见改变时,通常不调用VisibleChanged。

其他回答

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

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

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

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 !!然后,当....时,您开始严格检查是否没有竞态条件浪费了一个小时之后……你发现这只是一个微小的可枚举的东西,你忘记了....

看看这个:

class Program
{
    static void Main(string[] args)
    {
        var originalNumbers = new List<int> { 1, 2, 3, 4, 5, 6 };

        var list = new List<int>(originalNumbers);
        var collection = new Collection<int>(originalNumbers);

        originalNumbers.RemoveAt(0);

        DisplayItems(list, "List items: ");
        DisplayItems(collection, "Collection items: ");

        Console.ReadLine();
    }

    private static void DisplayItems(IEnumerable<int> items, string title)
    {
        Console.WriteLine(title);
        foreach (var item in items)
            Console.Write(item);
        Console.WriteLine();
    }
}

输出是:

List items: 123456
Collection items: 23456

接受IList的集合构造函数会对原始List创建一个包装器,而List构造函数会创建一个新List并将所有引用从原始List复制到新List。

点击这里查看更多信息: http://blog.roboblob.com/2012/09/19/dot-net-gotcha-nr1-list-versus-collection-constructor/

递归属性有问题

我认为不是c#特有的,而且我确信我在SO的其他地方看到过它(这个问题让我想起了它)

它有两种发生方式,但最终结果是一样的:

忘记引用基数。当重写一个属性时:

 public override bool IsRecursive
 {
     get { return IsRecursive; }
     set { IsRecursive = value; }
 }

从auto-属性改为back -属性,但并没有完全改变:

public bool IsRecursive
{
    get { return IsRecursive; }
    set { IsRecursive = value; }
}

我来这个派对有点晚了,但我最近有两个问题都困扰着我:

DateTime决议

Ticks属性以千万分之一秒(100纳秒块)为单位测量时间,但是分辨率不是100纳秒,而是大约15毫秒。

这段代码:

long now = DateTime.Now.Ticks;
for (int i = 0; i < 10; i++)
{
    System.Threading.Thread.Sleep(1);
    Console.WriteLine(DateTime.Now.Ticks - now);
}

将给你一个输出(例如):

0
0
0
0
0
0
0
156254
156254
156254

类似地,如果查看DateTime.Now。毫秒,您将得到以15.625毫秒为单位的四舍五入块的值:15、31、46等等。

这种特殊的行为因系统而异,但是在这个日期/时间API中还有其他与解析相关的问题。


路径。结合

一种组合文件路径的好方法,但它并不总是按您期望的方式运行。

如果第二个参数以\字符开头,它不会给你一个完整的路径:

这段代码:

string prefix1 = "C:\\MyFolder\\MySubFolder";
string prefix2 = "C:\\MyFolder\\MySubFolder\\";
string suffix1 = "log\\";
string suffix2 = "\\log\\";

Console.WriteLine(Path.Combine(prefix1, suffix1));
Console.WriteLine(Path.Combine(prefix1, suffix2));
Console.WriteLine(Path.Combine(prefix2, suffix1));
Console.WriteLine(Path.Combine(prefix2, suffix2));

给出如下输出:

C:\MyFolder\MySubFolder\log\
\log\
C:\MyFolder\MySubFolder\log\
\log\

LinqToSql批处理速度随着批处理大小的平方而变慢

以下是我探索这个问题的问题(和答案)。

In a nutshell, if you try to build up too many objects in memory before calling DataContext.SubmitChanges(), you start experiencing sluggishness at a geometric rate. I have not confirmed 100% that this is the case, but it appears to me that the call to DataContext.GetChangeSet() causes the data context to perform an equivalence evaluation (.Equals()) on every single combination of 2 items in the change set, probably to make sure it's not double-inserting or causing other concurrency issues. Problem is that if you have very large batches, the number of comparisons increases proportionately with the square of n, i.e. (n^2+n)/2. 1,000 items in memory means over 500,000 comparisons... and that can take a heckuva long time.

为了避免这种情况,您必须确保对于预计有大量项目的任何批处理,您都在事务边界内完成整个工作,在创建每个项目时保存它,而不是在最后进行一次大保存。