常见错误1:没有考虑LINQ语句中底层对象
对于处理抽象操作集合LINQ是强大的,无论它们是内存的对象,数据库表,或者XML文档。在完美的世界中,你无须考虑底层对象是什么。但这里的错 误是假设我们生活在一个完美的世界中。事实上,当用完全相同的数据时相同的LINQ语句能返回不同的结果,如果这个数据以不同的格式给出的话。
例如,考虑如下语句:
1 2 3decimal total = (from account in myAccounts where account.Status == "active" select account.Balance).Sum();如果其中一个对象的 account.Status 等于 “Active”(注意大写A)会发生什么?好,如果myAccounts 是一个 DbSet 的对象(默认设置了不区分大小写的配置), where 表达式仍会匹配该元素。但是,如果 myAccounts 是在内存中的数组,那么它将不匹配,并将产生不同的总的结果。
等一下,在我们之前讨论字符串比较过程中,我们发现 == 操作符进行了字符串的顺序比较。那么,为什么在这个条件下, == 操作符表现出不区分大小写的比较呢?
答案是,当在LINQ语句中的底层对象都引用到SQL表中的数据(如在这个例子中,实体框架为DbSet对象的情况下),该语句被转换为一个T-SQL语句。操作符遵循T-SQL的规则,而不是C#的,所以在上述情况的比较中不区分大小写。
通常来说,尽管LINQ是一个有用的和以持续的方式查询对象的集合,但在现实中你仍然需要知道你的语句是否会被解释成顶着C#的帽子的其他类型的语句,以确保你代码的功能在运行时仍如预期的那样。
?
常见错误2:误解未初始化变量的默认值
在C#中,值类型不能为null。通过定义,值类型会有一个值,甚至没有初始化的值类型变量也必须有个值。这称为值类型的默认值。这会导致当检查一个变量是否初始化时不可预期的结果,如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15class Program { static Point point1; static Pen pen1; static void Main(string args) { Console.WriteLine(pen1 == null); // True Console.WriteLine(point1 == null); // False (huh ) }}
为什么 point1 不是null答案是 Point 是值类型,并且 Point 的默认值是(0,0),而不是null。没有认识到这点是C#中一个易犯(并且常见)的错误。
许多(但不是全部)值类型都有一个 IsEmpty 属性,你可以用这个属性来检查该值类型是否等于它的默认值:
1Console.WriteLine(point1.IsEmpty);// True当你去检查一个变量是否被初始化,确保你知道那个类型未被初始化的变量将有的默认值并且不依赖它为null。
常见错误3:使用不合适或者未特别指定的字符串比较方法在C#中有许多不同的方法比较字符串。
尽管许多程序员用 == 操作符来比较字符串,但其实这是许多方法中最不理想的方法之一,主要是因为它在代码中没有明确指明需要哪一种比较。
相反,在C#中测试字符串想等的首选方式是使用 Equals 方法:
1 2 3public bool Equals(string value); public bool Equals(string value, StringComparison comparisonType);第一个方法的签名(例如,没有 comparisonType 参数),实际上和使用 == 操作符完全一样,但具有对字符串明确化的好处。它执行一个字符串的序号比较,基本上就是字节与字节比较。在许多情况下,这正是你想要的比较类型,特别是当 比较的字符串的值参数化,例如文件名,环境变量,属性等等。在这种情况下,只要顺序比较的确是这种情况下正确的类型比较即可,唯一的缺点是使用没有 comparisonType 的 Equals 方法,会使得某些读你代码的人不知道你用什么比较类型做的比较。
使用带 comparisonType 参数的 Equals 方法,你每次比较字符串的时候,虽说,不光会使得你的代码更清晰,而且会使你明确你需要使用的比较类型。这是值得做的事情,因为尽管英语在按顺序比较与语 言区域性比较之间没什么差异,但其他语言提供了很多,而忽略其他语言的可能性则为你自己在未来的路上提供了犯很多错误的可能。例如:
1 2 3 4 5 6 7 8 9 10 11 12string s = "strasse"; // outputs False: Console.WriteLine(s == "strae"); Console.WriteLine(s.Equals("strae")); Console.WriteLine(s.Equals("strae", StringComparison.Ordinal)); Console.WriteLine(s.Equals("Strae", StringComparison.CurrentCulture)); Console.WriteLine(s.Equals("strae", StringComparison.OrdinalIgnoreCase)); // outputs True: Console.WriteLine(s.Equals("strae", StringComparison.CurrentCulture)); Console.WriteLine(s.Equals("Strae", StringComparison.CurrentCultureIgnoreCase));最安全的实践是总是为 Equals 方法提供一个 comparisonType 参数。这是一些基本准则:
·当比较有用户输入的字符串,或者将显示给用户的字符串,使用本地化比较(CurrentCulture 或者 CurrentCultureIgnoreCase)。
·当比较程序设计用的字符串,使用原始比较(Ordinal 或者 OrdinalIgnoreCase)。
·InvariantCulture 和 InvariantCultureIgnoreCase 通常并不使用,除非在受限的条件下,因为原始比较更加有效。如果本地性文化比较是必须的话,它应该基于当前文化或另一个明确的文化来执行。
此外,对于 Equals 方法来说,字符串也提供了 Compare 方法,用来给你提供关于字符串相对顺序信息而不仅仅测试是否相等。这个方法更适用 和>= 操作符,与上文讨论的原因相同。
更多Java语言知识 = 操作符,与上文讨论的原因相同。
更多Java语言知识 ,欢迎进入良师益友网
C# 程序员易犯什么错误
评论
1 views