2

Why not to create a possibility to delete objects in C# as in C++ as a alternative but not required action?

For example when we want to clean memory from 500 Mb object after it not necessary any more to not wait for GC(Garbage collector)

Yuri Molchanov
  • 131
  • 1
  • 1
  • 9
  • GC.Collect();GC.Collect(); call it twice. But the question is why do you care? – Access Denied Sep 20 '18 at 08:49
  • 2
    If those 500 Mb are from unmanaged resources, check your `IDisposable` objects, otherwise check if the scope of the elements (static vs class vs method) is the correct one and assign to null elements not longer used within that scope. – Cleptus Sep 20 '18 at 08:51
  • 3
    The whole point of a **managed** language such as .NET is, that there *is* a garbage-colelctor that deletes all the orphaned objects. So you don´t have to care for this mch, unless you have some **unmanaged** ressources, which GC can´t handle at all. – MakePeaceGreatAgain Sep 20 '18 at 08:52
  • 1
    This about the time you need to look at [Garbage Collection](https://learn.microsoft.com/en-us/dotnet/standard/garbage-collection/) – TheGeneral Sep 20 '18 at 09:06
  • Possible duplicate of [Manually destroy C# objects](https://stackoverflow.com/questions/1987251/manually-destroy-c-sharp-objects) – Rene Knop Sep 20 '18 at 09:14
  • @ReneKnop It is more related than duplicated. In fact the best advice in that question's answer that could be useful to memory usage in my opinion is "using Dispose to unlink events/delegates" – Cleptus Sep 20 '18 at 15:42
  • The reason of my question is more like suggestion. Why? Because still as .Net grows and updating but the biggest games are written with C++ or with java in most – Yuri Molchanov Sep 20 '18 at 20:45
  • Stackoverflow is not a good place for suggestions. Post it to github: https://github.com/Microsoft/dotnet/issues – Access Denied Sep 21 '18 at 03:10

6 Answers6

4

The whole point of a managed language such as .NET is, that there is a garbage-collector that deletes all the orphaned objects. These are all the objects to which no references exist. For example in the following example when program reaches the end of the DoSomething method, all references to the created object of type MyClass are lost and the object itself is marked for deletion. However the GC decides when to do this.

void SoSomething()
{
    var m = new MyClass();
}

So you don´t have to care for this much, unless you have some unmanaged resources, which GC can´t handle at all.

So you seem to have some big design-problem in your program. You either have far too many objects in GC-state 2 which are long-lived and thus not collected (static variables for example), or there are many unmanaged resources such as file-handlers which GC can´t handle.

In the first case you should limit the scope of your variables as much as possible.

In the second case you should use the Dispose method for every such resource. This is easiest done with a using, which will call IDisposable.Dipose() automatically when an exception occurs or when the codeblock is done. Calling Dispose will ensure the unmanaged memory is released. However the remaining managed part of the object still remains in memory. However this will soon be garbage-collected as soon as all the references to it are gone, hence the importance of variable scope.

using (FileStream fs = File.Create(path))
{
    // do something with the file
}
MakePeaceGreatAgain
  • 35,491
  • 6
  • 60
  • 111
  • I would suggest: 1- Adding https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-statement for those `IDisposable` of the second case. 2- Mention that `GC.Collect()` is not magic, is resource was not closed/disposed it will not be freed. – Cleptus Sep 20 '18 at 09:04
  • Maybe silly to even suggest but there's at least one instance where the DoSomething example *wouldnt* be reclaimable after the method: if MyClass's constructor added the newly created object (this) to a static collection... Though that would be covered by point two. Just calling out that there are exceptions to the rule in the event something else is going on – pinkfloydx33 Sep 20 '18 at 09:22
  • 1
    @pinkfloydx33 What you mention is the first case, variable scope/long lived(`static IDisposable`) objects would not be reclaimed by GB and should be manually disposed. – Cleptus Sep 20 '18 at 09:36
1

You can use GC.Collect(); to force a collection by the Garbage Collector, but this is normally not recommended unless you have a good reason and you know what you're doing.

If you have a way to reach the object you want to destroy, it is actually impossible to destroy that object - the collector will not collect an object that is reachable.

If the object you want to destroy is an unmanaged object, then wrap it with using or remember to dispose of it.

1

I will add my 50 cents regarding GC. If you have lots of large unmanaged objects .NET does not know that you eat much memory and you need to add Memory Pressure to notify how many bytes are allocated in reality:

GC.AddMemoryPressure(long bytes)

An example can be found here:

http://adavesh.blogspot.com/2012/02/gcaddmemorypressure-working-with-native.html

Access Denied
  • 8,723
  • 4
  • 42
  • 72
  • 2
    I didn't know that existed :-) I'm not OP but thank you. – ProgrammingLlama Sep 20 '18 at 09:10
  • Best fitted in the comments, but `GC.AddMemoryPressure` is really interesting. I wonder if having to use it is a sign of code smell or poor amount of resources tho. – Cleptus Sep 20 '18 at 09:40
  • @bradbury9 people usually don't know about it and think they have memory leak and call GC.Collect to fix this so called "memory leak". You have to use it if you have to deal with large unmanaged resources which are commonly handled by system classes and in most cases you don't see how it works under the hood. And it's not the sign of the bad code if you use it. – Access Denied Sep 20 '18 at 09:45
0

If the object you are working with implements IDisposable within its class then you can call my_object.Dispose(); to manually remove memory allocation.

You can also force the garbage collector to run using System.GC.Collect() though this is not recommended.

Mark
  • 691
  • 7
  • 20
0

This is how generational GC works. Unlike C++ it doesn't have map of free space to allocate new object. It just allocates new objects down the memory space after previous allocation. When GC happens, objects that still needs to be kept in memory are compacted and physically moved in memory.

So, even if you could deallocate single object memory allocator won't use that memory segment until next GC happens and it makes no sense to deallocate just one object.

Of course, there are more details in GC like different generations, Large objects heap, multiple segments for generations, but overall removing just one object is useless.

dlxeon
  • 1,932
  • 1
  • 11
  • 14
0

In languages that allow objects to be explicitly freed, it is possible for a reference to a freed object to spontaneously become a seemingly-valid reference to an unrelated object. For example, in C, given:

FILE *f = fopen("file1", "w");
...
fclose(f);
FILE *g = fopen("file2", "w");
...
fprintf(f,"Hey there!");

it's possible that by the time the fprintf is performed, the FILE identified by f will have been recycled for use with file2. In general, there is no cheap way for a language to guard against such mistakes.

One of the major benefits of a reachability-based GC is that such a thing simply cannot happen. If one performs:

someStreamType f = openStreamSomewhow(...);
f.Dispose();
someStreamType g = openStreamSomewhow(...);
f.outputData(...);

then at the time outputData is called, f will hold a reference to a disposed stream object. As long as any copy of that reference exists anywhere in the universe, it will continue to identify that same dead object.

Neither Java nor .NET can safely recycle the storage used by an object unless they can be certain that no references to it exist. Making such determination for a large number of objects simultaneously is much cheaper than making it for individual objects, so being told that it's likely that no references to some particular object will exist wouldn't really be very helpful.

supercat
  • 77,689
  • 9
  • 166
  • 211