C# .net 3.5中的坑点/惊喜

3
一位熟识且曾经共事的人突然打电话给我,向我提供一份无法忽视的合同。他确信我可以在很短时间内掌握C#(我之前有C/C++、PHP、Python和Lua的经验)。
这个问题与我的另外两个问题相一致: PHP常见错误 Python 2.x陷阱和错误

这实际上是 https://dev59.com/b-o6XIcBkEYKwwoYTzRZ 的重复。 - cletus
嗯,我同意,也不同意。你链接的问题的目的是获取有用的技巧和知识。而这里的问题是可能会遇到的已知陷阱。虽然答案在很多方面可能是相同的,但这两个问题的意图对我来说似乎是不同的。 - Lasse V. Karlsen
我可能做的最糟糕的事情就是直接跳到学习新语言的技巧,我的问题意图在于尝试保持理智并避免任何常见但未记录的意外。 - David
7个回答

7
你希望在这里得到什么样的答案?
学习C#时需要注意的事项并不多,除了语法上的差异,如来自C、C++、Java和JavaScript等看起来像C#但实际上大相径庭的编程语言。
然而,你主要需要花费时间学习.NET基础类库,而非C#语言本身。
注:我并不是说在C#和.NET中没有“地雷”。我的意思是,根据你所描述的过去经验,你应该很快能掌握C#。但是我也认为,学习C#并不能代表你的全部学习经验。
就像你可以轻松地学会汽车手动换挡和自动换挡系统之间的区别,但是要充分利用系统还需要一些时间。
接下来回答你的问题,补充一个你可能会遇到的典型陷阱:
具体表现为:GC(垃圾回收)机制过于激进。
请考虑以下代码:
using System;
using System.Threading;
using System.Diagnostics;

namespace ConsoleApplication6
{
    class Program
    {
        static void Main(string[] args)
        {
            Thread t = new Thread(GCThread);
            t.IsBackground = true;
            t.Start();

            SomeClass sc = new SomeClass();
            sc.Test();
            Console.Out.WriteLine("Ending");
        }

        private static void GCThread()
        {
            while (true)
            {
                GC.Collect();
            }
        }
    }

    public class Disposable : IDisposable
    {
        public Boolean IsDisposed { get; set; }

        public void Dispose()
        {
            IsDisposed = true;
        }
    }

    public class SomeClass
    {
        private Disposable _Collectable = new Disposable();

        ~SomeClass()
        {
            _Collectable.Dispose();
            Console.Out.WriteLine("Finalized");
        }

        public void Test()
        {
            Console.Out.WriteLine("Test()");
            Disposable c = _Collectable;
            Debug.Assert(!_Collectable.IsDisposed);
            Thread.Sleep(100);
            Console.Out.WriteLine("c.IsDisposed: " + c.IsDisposed);
        }
    }

}

在我的电脑上,该对象如下:

Test()
Finalized
c.IsDisposed: True
Ending

在这里,我构建了一个SomeClass类型的对象,并调用了.Test方法。这个方法现在正在运行(毕竟我已经调用了它),它获取了内部变量_Collectable的一个副本,并断言它尚未被处理。
然而,在后台,垃圾回收器现在运行(我的后台线程确保尽可能经常地运行GC),它指示SomeClass完成自身的操作,即使我们的Test方法仍在执行,finalizer方法也会处理该对象。
因此,即使Debug.Assert确保IsDisposed属性为false,当输出到控制台时,对象已被处理,即使方法仍在运行。
垃圾回收器非常积极,即使我在这里强制它尽可能经常地运行,也不能保证它何时运行。因此,这段代码展示了你可能遇到的问题样例。

7
不要把C#看作是C++ - 它是一种不同的语言。学会使用和喜欢GC。在C++中,你创建的临时对象很常见,但在C#中会更加频繁。你仍然需要静态类型,但是使用C# 3时,语言将感觉更加流畅和灵活,特别是在使用lambda、匿名类型等方面。最重要的是学习和理解.NET框架库。了解其中的内容将节省您最多的时间,并帮助您以更“C#”方式编写代码。如果您需要快速掌握如何使自己的代码适应C#,请阅读Microsoft Design Guidelines for Class Libraries

2

我认为你从C#转向C/C++会遇到更多的问题。

如果你已经熟悉这些语言,可能只需要阅读一本教科书来了解C#的相关知识,但我相信你不会有太多问题。


2

1

0

不要在类定义后面加上“;”!

在C++中:

class MyClass {


};

在C#中:

class MyClass {


}

2
那不是会导致错误的东西...只是编译器错误,然后他会学习。 - Zifre

0

让我感到困惑的主要是缺乏复制构造函数和引用与值的区别。

查找ICloneable,并求助Jon Skeet!

从C++转到C#相当容易。我不认为我能忍受回去。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接