我最近正在使用一个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#陷阱分类会很有用。
下面的代码不会捕获. 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本质上做的事情与上面的代码完全相同,并且在没有堆栈跟踪的情况下崩溃。
重载==操作符和非类型化容器(数组列表、数据集等):
string my = "my ";
Debug.Assert(my+"string" == "my string"); //true
var a = new ArrayList();
a.Add(my+"string");
a.Add("my string");
// uses ==(object) instead of ==(string)
Debug.Assert(a[1] == "my string"); // true, due to interning magic
Debug.Assert(a[0] == "my string"); // false
解决方案?
总是使用字符串。当比较字符串类型时等于(a, b)
使用像List<string>这样的泛型来确保两个操作数都是字符串。
相关对象和外键不同步
微软已经承认了这个漏洞。
我有一个类Thing,它有一个FK到Category。Category与Thing之间没有定义的关系,以免污染接口。
var thing = CreateThing(); // does stuff to create a thing
var category = GetCategoryByID(123); // loads the Category with ID 123
thing.Category = category;
Console.WriteLine("Category ID: {0}", thing.CategoryID);
输出:
Category ID: 0
类似的:
var thing = CreateThing();
thing.CategoryID = 123;
Console.WriteLine("Category name: {0}", order.Category.Name);
抛出NullReferenceException。相关对象Category不加载ID为123的Category记录。
但是,在向DB提交更改之后,这些值将得到同步。但是在您访问DB之前,FK值和相关对象的功能实际上是独立的!
(有趣的是,同步FK值与相关对象的失败似乎只发生在没有定义子关系的情况下,即Category没有“Things”属性。但当你只是设置FK值时,“按需加载”永远不会起作用。)
明白了!
对于C/ c++程序员来说,过渡到c#是很自然的事情。然而,我个人遇到的最大的问题(以及其他人在做同样的转换时遇到的问题)是没有完全理解c#中类和结构之间的区别。
在c++中,类和结构是相同的;它们只在默认可见性上有所不同,其中类默认为私有可见性,结构默认为公共可见性。在c++中,这个类定义
class A
{
public:
int i;
};
在功能上等价于此结构定义。
struct A
{
int i;
};
然而,在c#中,类是引用类型,而结构是值类型。这在(1)决定何时使用一个而不是另一个,(2)测试对象的相等性,(3)性能(例如,装箱/拆箱)等方面产生了很大的差异。
网络上有各种各样的信息与两者之间的差异有关(例如,这里)。我强烈建议任何想要过渡到c#的人至少要了解这些差异及其含义。