.NET에서 사용한 후 개체를 Null / Nothing으로 설정
작업이 끝나면 모든 개체를 null
( Nothing
VB.NET에서) 로 설정해야합니까 ?
.NET에서는 IDisposable
일부 자원을 해제 하기 위해 인터페이스를 구현하는 객체 인스턴스를 처분해야한다는 것을 이해합니다. 하지만 객체는 폐기 된 후에도 무언가 (따라서 isDisposed
양식 의 속성) 일 수 있지만 여전히 상주 할 수 있다고 가정합니다. 기억이나 적어도 부분적으로?
또한 객체가 범위를 벗어나면 가비지 수집기의 다음 단계를 위해 수집 준비가 완료된 것으로 표시됩니다 (시간이 걸릴 수 있음).
따라서이를 염두에두고 null
메모리가 더 이상 범위에 있지 않으며 부작용이 없다는 것을 해결할 필요가 없으므로 메모리를 해제하는 시스템 속도를 높이도록 설정합니다 .
MSDN 기사는 예제 에서이 작업을 수행하지 않으며 현재 해를 볼 수 없으므로이 작업을 수행합니다. 그러나 나는 의견이 혼합되어있어 의견이 유용합니다.
Karl은 절대적으로 정확하므로 사용 후 객체를 null로 설정할 필요가 없습니다. 객체가을 구현하는 경우 해당 객체 ( .. 또는 블록에 싸여 있음)를 완료 IDisposable
하면 호출해야합니다 . 그러나을 호출하는 것을 기억하지 않아도 객체의 finaliser 메소드가 호출해야 합니다.IDisposable.Dispose()
try
finally
using()
Dispose()
Dispose()
나는 이것이 좋은 치료법이라고 생각했다.
이
자체 조정 및 불투명하기 때문에 GC 및 관리 전략을 다시 추측하려는 데는 아무런 의미가 없습니다. 여기에서 Dot Net Rocks의 Jeffrey Richter와의 내부 작업에 대한 좋은 토론이있었습니다. Windows 메모리 모델에 관한 Jeffrey Richter 및 C # 20 장을 통한 Richters 책 CLR 은 대단한 대우 를 받았습니다 .
작업을 완료 할 때 개체를 null로 설정하지 않는 또 다른 이유는 실제로 개체를 더 오래 살릴 수 있기 때문입니다.
예 :
void foo()
{
var someType = new SomeType();
someType.DoSomething();
// someType is now eligible for garbage collection
// ... rest of method not using 'someType' ...
}
"DoSomething"을 호출 한 후 someType에 의해 참조 된 객체를 GC 할 수 있지만
void foo()
{
var someType = new SomeType();
someType.DoSomething();
// someType is NOT eligible for garbage collection yet
// because that variable is used at the end of the method
// ... rest of method not using 'someType' ...
someType = null;
}
때로는 메소드가 끝날 때까지 객체를 활성 상태로 유지할 수 있습니다. JIT 보통 NULL로 지정을 얻어 최적화 된 것 같은 코드 인 것을 단부의 두 비트 있도록.
객체를 null하지 않습니다. 당신은 체크 아웃 할 수 http://codebetter.com/blogs/karlseguin/archive/2008/04/27/foundations-of-programming-pt-7-back-to-basics-memory.aspx을 자세한 정보는하지만, 사물을 null로 설정하면 더러운 코드를 제외하고는 아무것도하지 않습니다.
또한:
using(SomeObject object = new SomeObject())
{
// do stuff with the object
}
// the object will be disposed of
일반적으로 사용 후 객체를 null로 지정할 필요는 없지만 어떤 경우에는 좋은 방법입니다.
객체가 IDisposable을 구현하고 필드에 저장되면 배치 된 객체를 사용하지 않기 위해 null로 만드는 것이 좋습니다. 다음과 같은 종류의 버그는 고통 스러울 수 있습니다.
this.myField.Dispose();
// ... at some later time
this.myField.DoSomething();
필드를 삭제 한 후 필드를 null로 설정하고 필드를 다시 사용하는 줄에서 NullPtrEx를 가져 오는 것이 좋습니다. 그렇지 않으면 DoSomething의 기능에 따라 약간의 버그가 발생할 수 있습니다.
Chances are that your code is not structured tightly enough if you feel the need to null
variables.
There are a number of ways to limit the scope of a variable:
As mentioned by Steve Tranby
using(SomeObject object = new SomeObject())
{
// do stuff with the object
}
// the object will be disposed of
Similarly, you can simply use curly brackets:
{
// Declare the variable and use it
SomeObject object = new SomeObject()
}
// The variable is no longer available
I find that using curly brackets without any "heading" to really clean out the code and help make it more understandable.
The only time you should set a variable to null is when the variable does not go out of scope and you no longer need the data associated with it. Otherwise there is no need.
In general no need to set to null. But suppose you have a Reset functionality in your class.
Then you might do, because you do not want to call dispose twice, since some of the Dispose may not be implemented correctly and throw System.ObjectDisposed exception.
private void Reset()
{
if(_dataset != null)
{
_dataset.Dispose();
_dataset = null;
}
//..More such member variables like oracle connection etc. _oraConnection
}
this kind of "there is no need to set objects to null after use" is not entirely accurate. There are times you need to NULL the variable after disposing it.
Yes, you should ALWAYS call .Dispose()
or .Close()
on anything that has it when you are done. Be it file handles, database connections or disposable objects.
Separate from that is the very practical pattern of LazyLoad.
Say I have and instantiated ObjA
of class A
. Class A
has a public property called PropB
of class B
.
Internally, PropB
uses the private variable of _B
and defaults to null. When PropB.Get()
is used, it checks to see if _PropB
is null and if it is, opens the resources needed to instantiate a B
into _PropB
. It then returns _PropB
.
To my experience, this is a really useful trick.
Where the need to null comes in is if you reset or change A in some way that the contents of _PropB
were the child of the previous values of A
, you will need to Dispose AND null out _PropB
so LazyLoad can reset to fetch the right value IF the code requires it.
If you only do _PropB.Dispose()
and shortly after expect the null check for LazyLoad to succeed, it won't be null, and you'll be looking at stale data. In effect, you must null it after Dispose()
just to be sure.
I sure wish it were otherwise, but I've got code right now exhibiting this behavior after a Dispose()
on a _PropB
and outside of the calling function that did the Dispose (and thus almost out of scope), the private prop still isn't null, and the stale data is still there.
Eventually, the disposed property will null out, but that's been non-deterministic from my perspective.
The core reason, as dbkk alludes is that the parent container (ObjA
with PropB
) is keeping the instance of _PropB
in scope, despite the Dispose()
.
There are some cases where it makes sense to null references. For instance, when you're writing a collection--like a priority queue--and by your contract, you shouldn't be keeping those objects alive for the client after the client has removed them from the queue.
But this sort of thing only matters in long lived collections. If the queue's not going to survive the end of the function it was created in, then it matters a whole lot less.
On a whole, you really shouldn't bother. Let the compiler and GC do their jobs so you can do yours.
Take a look at this article as well: http://www.codeproject.com/KB/cs/idisposable.aspx
For the most part, setting an object to null has no effect. The only time you should be sure to do so is if you are working with a "large object", which is one larger than 84K in size (such as bitmaps).
Stephen Cleary explains very well in this post: Should I Set Variables to Null to Assist Garbage Collection?
Says:
The Short Answer, for the Impatient Yes, if the variable is a static field, or if you are writing an enumerable method (using yield return) or an asynchronous method (using async and await). Otherwise, no.
This means that in regular methods (non-enumerable and non-asynchronous), you do not set local variables, method parameters, or instance fields to null.
(Even if you’re implementing IDisposable.Dispose, you still should not set variables to null).
The important thing that we should consider is Static Fields.
Static fields are always root objects, so they are always considered “alive” by the garbage collector. If a static field references an object that is no longer needed, it should be set to null so that the garbage collector will treat it as eligible for collection.
Setting static fields to null is meaningless if the entire process is shutting down. The entire heap is about to be garbage collected at that point, including all the root objects.
Conclusion:
Static fields; that’s about it. Anything else is a waste of time.
I believe by design of the GC implementors, you can't speed up GC with nullification. I'm sure they'd prefer you not worry yourself with how/when GC runs -- treat it like this ubiquitous Being protecting and watching over and out for you...(bows head down, raises fist to the sky)...
Personally, I often explicitly set variables to null when I'm done with them as a form of self documentation. I don't declare, use, then set to null later -- I null immediately after they're no longer needed. I'm saying, explicitly, "I'm officially done with you...be gone..."
Is nullifying necessary in a GC'd language? No. Is it helpful for the GC? Maybe yes, maybe no, don't know for certain, by design I really can't control it, and regardless of today's answer with this version or that, future GC implementations could change the answer beyond my control. Plus if/when nulling is optimized out it's little more than a fancy comment if you will.
I figure if it makes my intent clearer to the next poor fool who follows in my footsteps, and if it "might" potentially help GC sometimes, then it's worth it to me. Mostly it makes me feel tidy and clear, and Mongo likes to feel tidy and clear. :)
I look at it like this: Programming languages exist to let people give other people an idea of intent and a compiler a job request of what to do -- the compiler converts that request into a different language (sometimes several) for a CPU -- the CPU(s) could give a hoot what language you used, your tab settings, comments, stylistic emphases, variable names, etc. -- a CPU's all about the bit stream that tells it what registers and opcodes and memory locations to twiddle. Many things written in code don't convert into what's consumed by the CPU in the sequence we specified. Our C, C++, C#, Lisp, Babel, assembler or whatever is theory rather than reality, written as a statement of work. What you see is not what you get, yes, even in assembler language.
I do understand the mindset of "unnecessary things" (like blank lines) "are nothing but noise and clutter up code." That was me earlier in my career; I totally get that. At this juncture I lean toward that which makes code clearer. It's not like I'm adding even 50 lines of "noise" to my programs -- it's a few lines here or there.
There are exceptions to any rule. In scenarios with volatile memory, static memory, race conditions, singletons, usage of "stale" data and all that kind of rot, that's different: you NEED to manage your own memory, locking and nullifying as apropos because the memory is not part of the GC'd Universe -- hopefully everyone understands that. The rest of the time with GC'd languages it's a matter of style rather than necessity or a guaranteed performance boost.
At the end of the day make sure you understand what is eligible for GC and what's not; lock, dispose, and nullify appropriately; wax on, wax off; breathe in, breathe out; and for everything else I say: If it feels good, do it. Your mileage may vary...as it should...
I think setting something back to null is messy. Imagine a scenario where the item being set to now is exposed say via property. Now is somehow some piece of code accidentally uses this property after the item is disposed you will get a null reference exception which requires some investigation to figure out exactly what is going on.
I believe framework disposables will allows throw ObjectDisposedException which is more meaningful. Not setting these back to null would be better then for that reason.
Some object suppose the .dispose()
method which forces the resource to be removed from memory.
참고URL : https://stackoverflow.com/questions/2785/setting-objects-to-null-nothing-after-use-in-net
'Programming' 카테고리의 다른 글
C #에서 프리미티브의 ==와 Equals ()의 차이점은 무엇입니까? (0) | 2020.05.19 |
---|---|
/ proc / self / exe없이 현재 실행 파일 경로 찾기 (0) | 2020.05.19 |
자식 요소에 따라 요소에 CSS 스타일 적용 (0) | 2020.05.18 |
작업 표시 줄과 새로 도입 된 도구 모음의 차이점은 무엇입니까? (0) | 2020.05.18 |
.pid 파일이란 무엇이며 무엇을 포함합니까? (0) | 2020.05.18 |