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


当前回答

LINQ to SQL和一对多关系

这是一个可爱的,咬了我几次,微软把它留给他们自己的开发人员放在她的博客。我不能说得比她更好,来看看。

其他回答

LINQ to SQL和一对多关系

这是一个可爱的,咬了我几次,微软把它留给他们自己的开发人员放在她的博客。我不能说得比她更好,来看看。

有一本关于。net gottchas的书

我最喜欢的是你在c#中创建一个类,继承它到VB,然后试图重新继承回c#,它不起作用。ARGGH

类型。方法

我见过的咬了很多人的是Type.GetType(string)。他们想知道为什么它适用于自己程序集中的类型,以及一些类型,如System。字符串,而不是System.Windows.Forms.Form。答案是,它只能在当前程序集中和mscorlib中查找。


匿名方法

c# 2.0引入了匿名方法,导致了下面这种糟糕的情况:

using System;
using System.Threading;

class Test
{
    static void Main()
    {
        for (int i=0; i < 10; i++)
        {
            ThreadStart ts = delegate { Console.WriteLine(i); };
            new Thread(ts).Start();
        }
    }
}

打印出来的是什么?嗯,这完全取决于日程安排。它会输出10个数字,但它可能不会输出0 1 2 3 4 5 6 7 8 9这是你可能期望的。问题是被捕获的是变量i,而不是它在创建委托时的值。这可以用一个合适范围的额外局部变量轻松解决:

using System;
using System.Threading;

class Test
{
    static void Main()
    {
        for (int i=0; i < 10; i++)
        {
            int copy = i;
            ThreadStart ts = delegate { Console.WriteLine(copy); };
            new Thread(ts).Start();
        }
    }
}

迭代器块的延迟执行

这个“穷人单元测试”没有通过——为什么?

using System;
using System.Collections.Generic;
using System.Diagnostics;

class Test
{
    static IEnumerable<char> CapitalLetters(string input)
    {
        if (input == null)
        {
            throw new ArgumentNullException(input);
        }
        foreach (char c in input)
        {
            yield return char.ToUpper(c);
        }
    }
    
    static void Main()
    {
        // Test that null input is handled correctly
        try
        {
            CapitalLetters(null);
            Console.WriteLine("An exception should have been thrown!");
        }
        catch (ArgumentNullException)
        {
            // Expected
        }
    }
}

答案是,在迭代器的MoveNext()方法第一次被调用之前,CapitalLetters代码源中的代码不会被执行。

我的脑筋急转弯页面上还有一些奇怪的东西。

LinqToSQL和空集聚合

看这个问题。

如果你有一个LinqToSql查询,你正在运行一个聚合——如果你的结果集是空的,Linq不能计算出数据类型是什么,即使它已经声明了。

例:假设你有一个带有Amount字段的Claim表,它在LinqToSql中是十进制类型。

var sum = Claims.Where(c => c.ID < 0).Sum(c => c.Amount);

显然,没有任何声明的ID小于零,因此应该看到sum = null,对吧?错了!您会得到一个InvalidOperationException,因为Linq查询底层的SQL查询没有数据类型。你必须明确地告诉Linq它是一个小数!因此:

var sum = Claims.Where(c => c.ID < 0).Sum(c => (decimal?)c.Amount);

这真的很愚蠢,在我看来,这是微软的设计错误。

明白了!

ASP。NET:

如果你正在使用Linq-To-SQL,你在数据上下文中调用SubmitChanges(),它会抛出一个异常(例如,重复的键或其他约束违反),当你调试时,有问题的对象值会保留在你的内存中,并且每次你随后调用SubmitChanges()时都会重新提交。

现在真正的问题是:即使您在IDE中按下“停止”按钮并重新启动,坏值仍将保留在内存中!我不明白为什么有人认为这是一个好主意-但小ASP。. NET图标弹出在您的系统托盘保持运行,它似乎保存您的对象缓存。如果你想冲洗你的内存空间,你必须右键单击该图标并强制关闭它!明白了!