Garbage Collection setting object to null [duplicate] - c#

This question already has answers here:
Garbage Collection: Is it necessary to set large objects to null in a Dispose method?
(6 answers)
Closed 9 years ago.
Given
public class A
{
public B First { get; set; }
}
public class B
{
public C Second { get; set;}
}
public class C
{
public D Third { get; set; }
}
And somewhere in the class you have this
var testClass = new A();
//All the properties have values in it and the class D has a property value that it is holding in to the memory
//testClass.B = new B();
//etc..
What happens if you did testClass = null? What does testClass's reference now to the heap? And what about D that is holding to a value that it can't collect?
EDIT: Just to clarify, given D has an event that hasn't been unsubscribed and has 10,000 handlers. What happens to testClass = null?

When you execute testClass = null, then the object remains on the heap. But there is no longer any reference to it in your code. It is eligible for garbage collection.
Any objects which are fields of A will no longer be referenced anywhere either. They will also be eligible for garbage collection.. and so on.
(As it happens, in your specific code, the fields First, Second and Third are never assigned. They are still null, so they don't really make any difference to the discussion).
Note that this collection probably won't happen straight away - setting testClass = null won't trigger a collection in itself.
If D references unmanaged resources, then it'll still be eligible for garbage collection when you set testClass = null. But unless D implements a Finalizer (which explicitly cleans up the unmanaged resources), then it will leak.
If D is an event with lots of subscriptions, then D will still be eligible for GC, even if you never explictly unsubscribe. See this answer here.
Following on, then if the subscriptions themselves are objects which are no longer referenced anywhere else, then they too will be eligible for collection.

Related

Can I set something up to make a class do something on unload

If I have a class,
class order()
{
int orderId {get;set;}
double total {get;set;}
public order(){}
...
}
Is there something I can overload so that c# does something every time it is going to be unloaded, instead of telling it I want it to be done?
static void Main(string[] args)
{
Order activeOrder = new Order();
// do stuff to the order
activeOrder = new Order(); <---- Automatically commit any changes to the order, since I am starting a new one.
}
What you're asking doesn't really make sense. When you assign a new Order instance to the activeOrder variable, the first Order instance isn't "unloaded". It just becomes eligible to garbage collection (unless it is also referenced somewhere else). This means that the next time the GC will run, the instance will be collected, and the finalizer will run if it's defined. The problem is that it's completely non-deterministic: you don't know when the GC will run.
There is no way for the Order class to detect that the variable is assigned a new instance. All you can do is write a finalizer, but since you don't know when it will run, it's probably not a good idea. You should commit the changes explicitly when you're done working with the current Order.
Thread-safety aside:
class Order()
{
static Order instance;
int orderId {get;set;}
double total {get;set;}
public Order()
{
if (instance != null)
instance.Unload();
instance = this;
}
...
public Unload()
{
}
}
This still leaves a question of who will unload the last instance of Order.

The .NET Garbage collector

This is a very basic question. I am debugging some memory leaks and got totally confused. Suppose I have the following:
public class ObjectData : IDataObject
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ObjectRepository<T> where T : IDataObject
{
private Dictionary<int, T> Objects;
public ObjectRepository()
{
Objects = new Dictionary<int, T>();
// load Data
}
public T GetDataObject(int id);
{
return Objects[id];
}
public Reset()
{
Objects = new Dictionary<int, T>();;
}
}
Now suppose I have the following program flow:
public Main()
{
var DataRepository = new ObjectRepository<ObjectData>();
// Constructor called and Data loaded
var myObject = DataRepository.GetDataObject(1);
DataRepository.Reset();
// Call manually the garbage collector or leave it
// Program flow continue after this
}
The question is, will the garbage collector get rid of the collection initially created by the constructor? Or it will not because one of the elements is still referenced in the program flow (myObject)?
It will be collected (eventually), since there is no more references to it. Getting a reference to something in a dictionary doesn't give you any reference to the dictionary itself! Unless that object somehow references the dictionary internally, that is.
To answer such questions ask yourself: Who is referencing the object in question (in this case the overwritten dictionary)?
DataRepository is not. You overwrote the object reference pointing to the old dictionary.
myObject is not because ObjectData does not have any field of type dictionary. It can't reference a dictionary.
Nobody is left to reference the old dictionary.
After your call to Reset, there is no strong references to your initial dictionary. Thus, it will be elected for garbage collection.
Or it will not because one of the elements is still referenced in the program flow (myObject)?
It doesn't matter which objects the dictionary refers to, what matters is who refers to the dictionary. In this case, no one. It's perfectly possible for the dictionary to be collected while its contents are still alive.

Set the instance to null not the variable referencing it

I created an object, and I assigned it to two variables found in separate classes.
If in one class I set the variable to null, it only breaks that reference to the object but the object itself still persists due to the other reference.
How do I set the object to null, so that both references point to null? Without finding every reference.
this is pseudocode. The idea is to lose the reference in both ClassA (ref1) and ClassB (ref2).
public class ClassA
{
public ClassC ref1 = new ClassC ();
static void Main(string[] args)
{
ref1 = null;
}
}
public class ClassB
{
public static ClassC ref2;
public static AssignC (ClassC c)
{
ref2 = c;
}
}
public class ClassC
{
public ClassC ()
{
ClassB.AssignC (this);
}
}
You can't.
You cannot reach into the internals of another class, (well, not conventionally.) This form of Encapsulation makes .Net code much easier to debug.
You could write a function on the class that sets all its members to null, you could do this as an implementation of IDisposable.
When there are no references to an object the Garbage Collector will reclaim the memory, you cannot directly control this.
You could rewrite your example like this.
public class A
{
private C c = new C();
static void Main(string[] args)
{
c.Dispose();
c = null;
}
}
public static class B
{
private static C c;
public static LastC
{
get
{
return c;
}
set
{
c = value;
}
}
}
public class C : IDisposable
{
public C()
{
B.C = this;
}
public void Dispose()
{
if (B.LastC == this)
{
// LastC has not been set by another instance.
B.LastC = null;
}
}
}
You'll note that I've made the static reference accessible via a setter, so that other classes can access it.
Setting null to reference-type variable change only VALUE of that particular variable - reference to object. Good article by Jon Skeet - http://www.yoda.arachsys.com/csharp/parameters.html
In your case its better to wrap object into Singleton pattern. So the setting of null to main variable will destroy the only reference to object and it can be garbage-collected.
It is simply not possible.
References can be either null or point to an actual instance. When you assign, as in ref2 = c; the value of one reference is copied to another reference. After that you have two references to the same instance. (The instance is not copied, for sure, only the reference; these are reference types.)
When you do ref1 = null; that just overwrites the particular reference with one that points to "nothing". It doesn't destroy any instance, just makes a single reference "point" to something else. Other references are unaffected (method parameters with ref or out of currently executing methods could in fact be the same reference, the one which is turned to points elsewhere).
In the question title you say "set the instance to null", but that doesn't really make sense, because an instance is an object (not a reference).
So how to destroy an instance? You can't. The garbage collector might come by at some point (when you are about to allocate a new object) and see that some instances have zero references to them. It will then remove the instances from memory.
You can't "zero" other people's references. Just because you have one references to an instance, there is no way to say "search through the entire application and find other references that happen to point to the same instance right now, and change all those references. That would be a really terrible thing to allow, because people could never be sure when their variables changed out of nowhere.

Object memory optimization question

Please pardon me for a n00bish question.
Please consider the following code:
public class SampleClass
{
public string sampleString { get; set; }
public int sampleInt { get; set; }
}
class Program
{
SampleClass objSample;
public void SampleMethod()
{
for (int i = 0; i < 10; i++)
{ objSample = new SampleClass();
objSample.sampleInt = i;
objSample.sampleString = "string" + i;
ObjSampleHandler(objSample);
}
}
private void ObjSampleHandler(SampleClass objSample)
{
//Some Code here
}
}
In the given example code, each time the SampleMethod() is called, it would iterate for 10 times and allocate new memory space for the instance of SampleClass and would assign to objSample object.
I wonder,
If this is a bad approach as a lot of
memory space is being wasted with it?
If that is the case, is there a
better approach to reuse/optimize the
allocated memory?
Or, Am I getting worried for no reason at all and getting into unneccesary micro optimisation mode ? :)
Edit: Also consider the situation when such a method is being used in a multi threaded enviornment. Would that change anything?
The technical term for what you are doing is premature optimization
You're definitely doing well to think about the performance implications of things. But in this case, the .NET Garbage Collector will handle the memory fine. And .NET is very good at creating objects fast.
As long as your class's constructor isn't doing a lot of complex, time-consuming things, this won't be a big problem.
Second option.
You shouldn't be concerned with this kind of optimization unless you're having a performance issue.
And even if you are, it would depend of what you do with the object after you create it, for example, if in ObjSampleHandler() you're storing the objects to use them later, you simply cannot avoid what you're doing.
Remember, "early optimization is the root of all evil" or so they say ;)
As you are creating a new object (objSample = new SampleClass();), you are not reusing that object. You are only reusing the reference to an instance of SampleClass.
But now you are forcing that reference to be a member-variable of your class Program, where it could have been a local variable of the method SampleMethod.
Assuming your code in ObjSampleHandler method doesnt create any non-local references to objSample, the object will become eligible for Garbage Collection once the method finishes, which will be quite memory efficient, and unlikely to be of concern.
However, if you are having problems specifically with the managed heap because of this type of code then you could change your class to a struct, and it will be stored on the Stack rather than the Heap which is more efficient. Please remember though that structs are copied by value rather than reference, and you need to understand the consequences of this in the remainder of your code.
public struct SampleClass
{
public string sampleString { get; set; }
public int sampleInt { get; set; }
}

What is the basic C# interface scope?

I am having a dispute with another fellow programmer, over the scope of interfaces.
suppose we have the following:
public interface IFoo
{
string Bar { get; set; }
}
public class SomeFoo: IFoo
{
public string Bar { get; set; }
public SomeFoo(string bar)
{
this.Bar = bar;
}
}
public class Consumer
{
public void DoSomething()
{
SomeFoo fooClassInstance = new SomeFoo("test");
IFoo fooInterface = (IFoo)fooClassInstance;
// do something with fooInterface.
}
}
So the question is:
1. Is it possible the fooClassInstance to go out of scope before something else releases the fooInterface instance?
Some argue that the object (fooClassInstance) can go out of scope.
I believe that it cant. Sure, objects may or may not get disposed of by the GC when the GC decides that the object(s) are no longer in scope. However since Interfaces are by design an abstract contract whose members have to be implemented by the object that uses it, than an interface cannot lose its implementation so long as the interface is used. It's not like a whole another object is created of type "interface". The interface is merely a pointer to those abstract members of the implementor.
Can you guys help me resolve this dispute?
Thanks,
<bleepzter />
While there is definitely some confusion in the terms you are using (I'll let someone else tackle that issue), I think I understand what you are saying, and you are basically right.
In particular, it sounds like your coworker believes this is happening:
// Now there is this "SomeFoo" object somewhere in memory.
SomeFoo fooClassInstance = new SomeFoo("test");
// Now there is this "IFoo" object somewhere in memory.
IFoo fooInterface = (IFoo)fooClassInstance;
// Let's say down the road somewhere, fooClassInstance is set to null or a different
// object. Your coworker believes that the object it originally pointed to will then
// have no references to it and will thus be eligible for garbage collection?
If the above is an accurate representation of what your coworker thinks, then your coworker is wrong and you are right. The fooInterface variable contains a reference to the same object that fooClassInstance had a reference to. You can easily verify this simply by doing the following:
SomeFoo fooClassInstance = new SomeFoo("test");
IFoo fooInterface = (IFoo)fooClassInstance;
bool sameObject = ReferenceEquals(fooClassInstance, fooInterface);
If ReferenceEquals returns true, then the two variables are referencing the same object in memory.
If your coworker needs further convincing, try showing him/her something like this:
List<int> list = new List<int> { 1, 2, 3 };
// This cast is actually not needed; I'm just including it so that it mirrors
// your example code.
IList<int> ilist = (IList<int>)list;
// Now we remove an item from the List<int> object referenced by list.
list.Remove(3);
// Is it in ilist? No--they are the same List<int> object.
Console.WriteLine(ilist.Contains(3));
// How about we remove an item using ilist, now?
ilist.Remove(2);
// Is it in list? Nope--same object.
Console.WriteLine(list.Contains(2));
// And here's one last thing to note: the type of a VARIABLE is not the same
// as the type of the OBJECT it references. ilist may be typed as IList<int>,
// but it points to an object that is truly a List<int>.
Console.WriteLine(ilist.GetType());
I think you are muddling the line between instance an reference. fooClassInstance can go out of scope (that is, it can no longer be referenced) even if the instance of the object still exists (because fooInterface still holds a reference to it).
For example, if you do the following, fooClassInstance will not be available after the braces, but fooInterface will.
public void DoSomething()
{
IFoo fooInterface;
{
SomeFoo fooClassInstance = new SomeFoo("test");
fooInterface = (IFoo)fooClassInstance;
}
// do something with fooInterface, but NOT with fooClassInstance
}
Uh, what do you mean by "lose its implementation"? That makes no sense. A type implements an interface, it cannot "unimplement" an interface.
As far as your code example goes, the lifetime of the object allocated ends the instant it no longer has any roots (aka, is no longer reachable by the GC). A reference to it is a reference to it, regardless of the type of the reference (i.e. if the reference type is of some derived or parent type, it doesn't matter).
ISomething Sample() {
Something s1 = new Something();
s2.DoSomething(); // Assuming s is the only reference to s, then it no longer is
// rooted after this expression
Something s2 = new Something();
ISomething is1 = s2;
s2 = null;
is1.DoSomething(); // The reference remains valid and the lifetime of the
// object created continues until we release all
// remaining references to it.
return is1;
}
It sounds like you are correct, but I feel like we're missing part of the discussion since we don't know what you're doing with the object after you create (and cast) it.
In your example:
SomeFoo fooClassInstance = new SomeFoo("test");
At this point, you have one reference to the SomeFoo object referenced by fooClassInstance.
IFoo fooInterface = (IFoo)fooClassInstance;
At this point, you have two references to the SomeFoo object (referenced by both fooClassInstance and fooInterface).
So yes, depending on how you use it, fooClassInstance could go out of scope. But there is still a reference to it (fooInterface) so it wouldn't be garbage collected. Also, the fooInterface reference could be cast back to SomeFoo.

Categories

Resources