C# 中真的需要构造函数或析构函数吗?
你能告诉我在 C# 中是否需要构造函数来设置属性的默认值?
同样,在语言被垃圾收集的地方是否需要析构函数?
请给我一些实际的例子。
Can you tell me is there any need for constructors in c# where properties are available to set default values?
Again, is there any need for destructors where the language is garbage collected?
Please give me some practical examples.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
构造函数对于初始化不可变数据至关重要。
他们还帮助声明 IoC/DI 期望/需求。
对于配置对象所需的最少数据集的情况,尽早要求它是有用的 - 这通常意味着构造函数。
析构函数/终结器通常用于释放非托管资源 - 例如操作系统句柄或来自非托管区域的内存 (
Marshal.AllocHGlobal
)。这些资源不会被垃圾收集,因此必须小心手动释放它们 - 否则会发生泄漏,或者使有限的池饱和。此类示例在应用程序代码中非常罕见,并且几乎总是用作IDisposable
之外的后备 - 当它未正确处置时。Constructors are essential to initialize immutable data.
They also help with declaring IoC/DI expectations/demands.
For scenarios where there is a minimal set of required data to configure an object, it is useful to demand it as early as possible - which often means the constructor.
Destructors/finalisers are used generally to release unmanaged resources - for example OS handles, or memory from the unmanaged area (
Marshal.AllocHGlobal
). These resources are not garbage collected, so care must be taken to release them manually - else a leak occurs, or you saturate limited pools. Such examples are pretty rare in application code, and are almost always used as a fallback in addition toIDisposable
- for when it doesn't get disposed correctly.在某些情况下,您会显式指定该类需要某些依赖项才能工作。在这种情况下,您可以使用构造函数注入:
现在该类的作者明确指出该类需要一些依赖项才能正常工作,因此为了实例化它,您需要提供此依赖项。
只要该语言是托管代码,就会被垃圾收集。但在托管代码中,您可以使用 P/Invoke 来调用非托管代码。非托管代码显然不再被垃圾收集。因此,您可以使用析构函数来释放非托管代码持有的资源(例如非托管句柄、非托管内存分配等)。
There are cases where you would explicitly specify that the class requires some dependency in order to work. In this case you could use constructor injection:
Now the author of the class explicitly states that this class needs some dependency in order to work properly, so in order to instantiate it you need to provide this dependency.
The language is garbage collected as long as it is managed code. But in managed code you could use P/Invoke to call unmanaged code. And unmanaged code is obviously no longer garbage collected. So you could use destructors to release resources hold by unmanaged code (things like unmanaged handles, unmanaged memory allocations, ...).
构造函数绝对必要的一个例子是不可变类型。否则您的字段如何获得其价值?
终结器(Spec 称其为析构函数,但在我看来这完全是愚蠢的)通常仅在使用非托管资源时才需要。但在大多数情况下,关键终结器(使用 SafeHandle 类系列)是正确的选择。
Dispose()
方法在处理非托管资源时很有用,而且如果您需要在销毁时执行某些操作(例如取消订阅事件)。它还与using
一起使用来创建 RAII 的低版本。One example where a constructor is absolutely necessary is with immutable types. How else would your fields get their value?
Finalizers(Spec calls them destructors, but that's utterly stupid IMO) are usually only necessary when working with unmanaged resources. But in most cases a critical finalizer (using the SafeHandle class family) is the correct choice for these.
The
Dispose()
method in useful when working with unmanaged resources, but also if you need to do something on destruction, such as unsubscribing from events. It's also used together withusing
to create an inferior version of RAII.每当创建一个对象并且我们希望自动执行一些代码时,可以使用构造函数。我们要执行的代码必须放在构造函数中。 C#构造函数的一般形式如下。
修饰符可以是private、public、protected或internal。构造函数的名称必须是定义它的类的名称。构造函数可以采用零个或多个参数。具有零参数(即无参数)的构造函数称为默认构造函数。请记住,构造函数没有返回类型。
下面的类包含一个构造函数,它带有两个参数。
以下代码段将在命令提示符下显示 20+i25。
也就是说,当我们创建Complex类的对象时,它会自动调用构造函数并初始化其数据成员x和y。可以说构造函数主要用于初始化一个对象。甚至可以在构造函数内进行非常复杂的计算。构造函数内的语句也可能引发异常。
析构函数
.NET 框架有一个称为垃圾收集的内置机制,用于释放未使用对象占用的内存。析构函数实现垃圾收集过程中要执行的语句。析构函数是一个与类名同名但以字符 ~ 开头的函数。
示例:
请记住,析构函数不能有任何修饰符,如 private、public 等。如果我们使用修饰符声明析构函数,编译器将显示错误。而且析构函数将只有一种形式,没有任何参数。 C# 中没有参数化析构函数。
析构函数是自动调用的,不能显式调用。当程序的活动部分不再使用某个对象时,该对象就符合垃圾回收的条件。析构函数的执行可以在实例或对象符合销毁条件后的任何时间发生。
A constructor can be used, where every time an object gets created and if we want some code to be executed automatically. The code that we want to execute must be put in the constructor. The general form of a C# constructor is as follows
The modifiers can be private,public, protected or internal.The name of a constructor must be the name of the class, where it is defined. A constructor can take zero or more arguments. A constructor with zero arguments (that is no-argument) is known as default constructor. Remember that there is not return type for a constructor.
The following class contains a constructor, which takes two arguments.
The following code segment will display 20+i25 on the command prompt.
That is when we create the object of the class Complex, it automatically calls the constructor and initializes its data members x and y. We can say that constructor is mainly used for initializing an object. Even it is possible to do very complicated calculations inside a constructor. The statement inside a constructor can throw exceptions also.
Destructors
The .NET framework has an in built mechanism called Garbage Collection to de-allocate memory occupied by the un-used objects. The destructor implements the statements to be executed during the garbage collection process. A destructor is a function with the same name as the name of the class but starting with the character ~.
Example:
Remember that a destructor can't have any modifiers like private, public etc. If we declare a destructor with a modifier, the compiler will show an error.Also destructor will come in only one form, without any arguments. There is no parameterized destructor in C#.
Destructors are invoked automatically and can't be invoked explicitly. An object becomes eligible for garbage collection, when it is no longer used by the active part of the program. Execution of destructor may occur at any time after the instance or object becomes eligible for destruction.
作为对 Marc 已经提到的内容的补充,自从 .NET 2.0 中引入 SafeHandle 以来,应该很少需要创建终结器。有关详细信息,请参阅 http://blogs.msdn.com /b/bclteam/archive/2005/03/16/396900.aspx 和 http://www.bluebytesoftware.com/blog/2005/12/27/NeverWriteAFinalizerAgainWellAlmostNever .aspx。
As a complement to what Marc has already mentioned, it should very rarely be necessary to create a finalizer since the introduction of SafeHandle in .NET 2.0. For details, see http://blogs.msdn.com/b/bclteam/archive/2005/03/16/396900.aspx and http://www.bluebytesoftware.com/blog/2005/12/27/NeverWriteAFinalizerAgainWellAlmostNever.aspx.