C#:对象变量应该分配为 null 吗?

发布于 2024-09-26 13:45:59 字数 59 浏览 3 评论 0原文

在 C# 中,如果您已经使用完一个对象变量,是否有必要将它分配给 null,即使它无论如何都会超出范围?

In C#, is it necessary to assign an object variable to null if you have finished using it, even when it will go out of scope anyway?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

夜吻♂芭芘 2024-10-03 13:45:59

不,这实际上可能是危险的并且容易出现错误(考虑一下有人可能稍后尝试使用它,而没有意识到它已被设置为空的可能性)。仅当有合理理由将某些内容设置为 null 时,才将其设置为 null。

No, and that could in fact be dangerous and bug-prone (consider the possibility that someone might try to use it later on, not realizing it had been set to null). Only set something to null if there's a logical reason to set it to null.

傲性难收 2024-10-03 13:45:59

在把车推到湖边之前你应该关掉它吗?
不,这是一个常见的错误,但没有任何区别。您没有将对象设置为null,而只是对其进行一个引用 - 该对象仍然在内存中,并且仍然必须由垃圾收集器收集。

Should you turn off your car before pushing it to the lake?
No. It is a common mistake, but it doesn't make any difference. You aren't setting the object to null, just one reference to it - the object is still in memory, and must still be collected by the garbage collector.

假扮的天使 2024-10-03 13:45:59

在我看来,更重要的是对实现了 IDisposable 的对象调用 Dispose。

除此之外,将 null 分配给引用变量仅意味着您明确指示范围的结束 - 大多数时候,这只是早期的一些指令(例如,方法主体中的局部变量)——随着编译器/JIT 优化的时代,运行时很可能会做同样的事情,所以你真的不会从中得到任何东西。在某些情况下,例如静态变量等,其范围是应用程序级别,如果您使用完变量,则应将变量分配为 null ,以便对象将被垃圾收集。

What matters more IMO is to call Dispose on objects that implement IDisposable.

Apart from that, assigning null to reference variables will just mean that you are explicitly indicating the end of scope — most of the time, it's just a few instructions early (for example, local variables in the method body) — with the era of compiler/JIT optimizations, its quite possible that runtime would do the same, so you really don't get anything out of it. In a few cases, such as static variables etc, whose scope is application level, you should assign a variable to null if you are done using it so that object will get garbage collected.

笑看君怀她人 2024-10-03 13:45:59

这些回答中的大多数都有正确的答案,但原因却是错误的。

如果它是局部变量,则该变量将在方法结束时从堆栈中退出,因此它指向的对象将少一个引用。如果该变量是对该对象的唯一引用,则该对象可用于 GC。

如果您将变量设置为 null(许多这样做的人被教导在方法结束时这样做),那么您实际上可能会延长对象在内存中保留的时间,因为 CLR 会认为该对象不能被收集直到方法结束,因为它看到了对下面对象的代码引用。但是,如果省略 null 设置,CLR 可以确定在代码中的某个点之后不再出现对该对象的调用,并且即使该方法尚未完成,GC 也可以收集该对象。

Most of these responses have the right answer, but for the wrong reasons.

If it's a local variable, the variable will fall off the stack at the end of the method and therefore the object it was pointing to will have one less reference. If that variable was the only reference to the object, then the object is available for GC.

If you set the variable to null (and many who do were taught to do it at the end of the method) then you could actually wind up extending the time the object stays in memory because the CLR will believe that the object can't be collected until the end of the method because it sees a code reference to the object way down there. However, if you omit the setting of null the CLR can determine that no more calls for the object appear after a certain point in your code and, even though the method hasn't completed yet, the GC can collect the object.

乖乖公主 2024-10-03 13:45:59

分配给 null 通常是一个坏主意:

  1. 从概念上讲,它毫无意义。
  2. 对于许多变量,您可能有足够的额外赋值为 null,从而明显增加了方法的大小。某些东西的源代码越长,阅读它所花费的精力就越多(即使其中大部分只是可以过滤掉的东西),并且更容易发现错误。仅当这样做更易于理解时,才使代码变得比必要的更加冗长。
  3. 您的空分配可能不会被优化掉。在这种情况下,编译后的代码可能不会执行真正的释放,直到它实际达到空赋值为止,而在大多数情况下,一旦变量除了超出范围(有时甚至之前)之外什么也不做。可以被解除分配。因此,您可能会对性能产生非常小的影响。

我唯一一次将某些内容分配给 null 来“清除”将不再使用的变量,而不是因为 null 实际上是我明确想要分配的值,是在两种可能的情况之一

  1. :一个可能寿命较长的对象,将不再被该对象使用,并且具有相当大的大小。这里分配为 null 是一种优化。
  2. 它是可能长期存在的对象的成员,将不再被该对象使用,因此已准备好释放其资源。这里分配给 null 是一个安全问题,因为发现意外使用 null 对象的情况比意外使用已处置对象的情况更容易。

这两种情况都不适用于局部变量,仅适用于成员,而且两者都很罕见。

Assigning to null is generally a bad idea:

  1. Conceptually, it's just pointless.
  2. With many variables, you could have enough extra assignments to null that you appreciably increase the size of the method. The longer the source code for something is, the more mental effort is taken to read it (even if much of it is just stuff that can be filtered out) and the easier it is to spot a bug. Make code more verbose than necessary only when doing so makes it more understandable.
  3. It is possible that your null assignment won't be optimised away. In that case it's possible that the compiled code won't do the real deallocation until it actually reaches that null assignment, whereas in most cases once the variable is going to do nothing else other than fall out of scope (and sometimes even before) it can be deallocated. You can therefore have a very minor performance impact.

The only time I would assign something to null to "clear" a variable that will no longer be used, rather than because null is actually a value I explicitly want to assign, is in one of the two possible cases:

  1. It is a member of a possibly long-lived object, will no longer be used by that object, and is of considerable size. Here assigning to null is an optimisation.
  2. It is a member of a possibly long-lived object, will no longer be used by that object, and has therefore been disposed to release its resources. Here assigning to null is a matter of safety as it can be easier to find a case where one accidentally uses a null object than where one accidentally uses a disposed object.

Neither of these cases apply to local variables, only to members, and both are rare.

此岸叶落 2024-10-03 13:45:59

不会。当涉及到局部变量时,是否有对象的引用根本没有区别,重要的是是否会使用该引用。

在代码中放置额外的空赋值不会对性能造成太大影响,也根本不会影响内存管理,但它会在代码中添加无动机的语句,从而降低可读性。

垃圾收集器知道代码中最后一次使用该引用的时间,因此它可以在不再需要该对象时立即收集该对象。

例子:

{
  // Create an object
  StringBuilder b = new StringBuilder();
  b.Append("asdf");
  // Here is the last use of the object:
  string x = b.ToString();
  // From this point the object can be collected whenever the GC feels like it
  // If you assign a null reference to the variable here is irrelevant
  b = null;
}

No. When it comes to local variables it makes no difference at all if you have a reference to the object or not, what matters is if the reference will be used or not.

Putting an extra null assignment in the code doesn't hurt performance much, and it doesn't affect memory management at all, but it will add unmotivated statements to the code that makes it less readable.

The garbage collector knows when the reference is used the last time in the code, so it can collect the object as soon as it's not needed any more.

Example:

{
  // Create an object
  StringBuilder b = new StringBuilder();
  b.Append("asdf");
  // Here is the last use of the object:
  string x = b.ToString();
  // From this point the object can be collected whenever the GC feels like it
  // If you assign a null reference to the variable here is irrelevant
  b = null;
}
音盲 2024-10-03 13:45:59

对于必须实现 IDisposable 的对象,作为实践,我在 IDisposable 的实现中将所有成员设置为 null。

很久以前,我发现这种做法极大地改善了 Windows Mobile 上运行的 .NET Compact Framework 应用程序的内存消耗和性能。我认为,与主 .NET Framework 相比,当时的 .NET Compact Framework 可能具有非常简约的垃圾收​​集器实现,并且在 IDisposable 实现中解耦对象的行为帮助 .NET Compact Framework 上的 GC 完成了它的任务。

这种做法的另一个原因是在对象上执行 IDisposable 后,实际上不希望任何东西尝试使用已处置对象上的任何成员。当然,理想情况下,您希望在尝试访问某个对象的任何函数时已释放的对象中出现 ObjectDisposeException,但用 NullReferenceException 代替它比没有异常要好。您想了解如何处理已释放对象的代码,因为滥用已释放的非托管资源可能会给应用程序带来很多麻烦。

注意: 我绝对不会提倡在对象上实现 IDisposable,除了将成员设置为 null 之外没有其他原因。我说的是当您出于其他原因需要实现 IDisposable 时,即您有实现 IDisposable 的成员或您的对象包装非托管资源。

For an object which has to implement IDisposable, as a practice I set all members to null in the implementation of IDisposable.

In the distant past I found this practice drastically improved the memory consumption and performance of a .NET Compact Framework application running on Windows Mobile. I think the .NET Compact Framework at the time probably had a very minimalistic implementation of the garbage collector compared to the main .NET Framework and the act of decoupling objects in the implementation of IDisposable helped the GC on the .NET Compact Framework do its thing.

An additional reason for this practice is after IDisposable has been executed on an object, it's actually undesirable for anything to attempt to use any of the members on a disposed object. Sure ideally you'd want an ObjectDisposedException out of an object which has been disposed when something attempts to access any of it's functions, but in place of that a NullReferenceException is better than no exception at all. You want to know about code messing with disposed objects as fooling around with unmanaged resources that have been released is something that can get an application into a lot of trouble.

NOTE: I'm definitely not advocating implementing IDisposable on an object for no other reason than to set members to null. I'm talking about when you need to implement IDisposable for other reasons, i.e. you have members which implement IDisposable or your object wraps unmanaged resources.

沉默的熊 2024-10-03 13:45:59

我想补充一点,据我所知,这只是 Visual Basic 单点版本的有效模式,甚至也有些争议。 (IIRC 它仅适用于 DAO 对象。)

I'd just like to add that AFAIK this was only a valid pattern for one point release of Visual Basic, and even that was somewhat debatable. (IIRC it was only for DAO objects.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文