为了账号安全,请及时绑定邮箱和手机立即绑定

在C#或.NET中最糟糕的陷阱是什么?

/ 猿问

在C#或.NET中最糟糕的陷阱是什么?

慕的地2183247 2020-02-03 14:05:53

我最近正在处理一个DateTime对象,并编写了如下内容:


DateTime dt = DateTime.Now;

dt.AddDays(1);

return dt; // still today's date! WTF?

的intellisense文档AddDays()说,它在日期上添加了一天,但实际上并没有-实际返回的日期中添加了一天,因此您必须这样写:


DateTime dt = DateTime.Now;

dt = dt.AddDays(1);

return dt; // tomorrow's date

之前,这已经咬了我很多次,所以我认为对最糟糕的C#陷阱进行分类将很有用。


查看完整描述

3 回答

?
慕尼黑8549860

private int myVar;

public int MyVar

{

    get { return MyVar; }

}

布拉莫 您的应用崩溃,没有堆栈跟踪。一直发生。


(注意使用大写MyVar字母而不是小写字母myVar)。


查看完整回答
反对 2020-02-03
?
千万里不及你

Type.GetType


我看到很多人咬过的是Type.GetType(string)。他们想知道为什么它适用于他们自己的程序集中的类型,而某些类型像System.String,而不是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

        }

    }

}

答案是,CapitalLetters直到MoveNext()首次调用迭代器的方法时,代码源中的代码才会执行。


我的脑筋急转弯页面上还有其他怪异之处。


查看完整回答
反对 2020-02-03
?
慕田峪7331174

重新抛出异常

重新抛出异常语义是获得许多新开发人员的陷阱。


很多时间我看到如下代码


catch(Exception e) 

{

   // Do stuff 

   throw e; 

}

问题在于,它会擦除堆栈跟踪,并使诊断问题变得更加困难,导致您无法跟踪异常的起源。


正确的代码是不带参数的throw语句:


catch(Exception)

{

    throw;

}

或将异常包装在另一个异常中,然后使用内部异常获取原始堆栈跟踪:


catch(Exception e) 

{

   // Do stuff 

   throw new MySpecialException(e); 

}


查看完整回答
反对 2020-02-03

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信