How to make a Sentry template in C #?

In C ++, I use the chat template to ensure that the resources received are correctly released when I exit a block or function (e.g. here ). I used this, for example, to capture the state of the graphic, and then I can do whatever I want in this state, and it returns when the object-object (link) goes out of scope.

Now I use C #, and the same trick does not work, because the destructor is not called until someone knows - when later.

Is there any OTHER method that is guaranteed to work when the last link of an object is released? Or do I just need to remember to call the Restore () or Apply () or DoYourThing () method before returning from any method in which I would use a sentinel?

+5
source share
5 answers

C # provides a using block for this case, which works on any object that implements IDisposable .

For example, if you have a class Foo : IDisposable type class Foo : IDisposable , you can do this:

 using (new Foo(/* ... */)) { // Your code that depends on this resource. } 

This is equivalent to:

 Foo x = new Foo(/* ... */); try { // Your code } finally { if (x != null) { ((IDisposable)x).Dispose(); } } 

Except, of course, that you do not have access to x . However, you can get this access if you need it by creating a variable in the using block:

 using (Foo foo = new Foo(/* ... */)) { // Your code that uses "foo" } 

The standard way to create a class that can be removed this way or by the garbage collector is as follows:

 class Foo : IDisposable { protected virtual void Dispose(bool disposing) { // Your cleanup code goes here. } public void Dispose() { GC.SuppressFinalize(this); Dispose(true); } ~Foo() { Dispose(false); } } 
+4
source

C # has finalizers, such as C ++, that are called when an object is destroyed. They are in the same form as C ++, namely:

 ~ClassName() { } 

As you know, C # does not have deterministic memory management, and therefore this is not a very big guarantee. As a direct result, you should not use finalizers to free unmanaged resources in C #. Instead, we use the IDisposable interface. This provides the only method for the Dispose developer to call when you want to free unmanaged resources.

 public class MyDisposable : IDisposable { public void Dispose() { // get rid of some expensive unmanaged resource like a connection } } 

We can also use using sugars to allow the semantic call of Dispose() when the using block completes (elegantly or not).

 using(var disposable = new MyDisposable) { // Do something with the disposable } // Dispose is invoked here 

If you find that you are using finalizers and Dispose , you can use the GC.SuppressFinalize method, although this is a bit out of my scope. StackOverflow had a really good discussion about it here

This can be used to fool RAII-esque, for example,

 using(var guard = new Guard(resource)) { } 
+12
source

To implement deterministic release of unmanaged resources, you must use the Dispose pattern. For many cases, you can combine this with the using block if you want this to happen in a specific area.

Graphic file descriptors or descriptors are generally considered an unmanaged resource. These are resources that the .NET platform does not track links and does not automatically release.

If this is a managed resource, just references to C # objects or lists, then usually deterministic release is not required, and the garbage collector can usually handle them more efficiently than you can. Do not worry about when managed resources will be released. If you no longer have a link to them, they should not bother you. Concerns arise when you do something, but somehow keep a long reference to it, which prevents GC from freeing it.

+2
source

It looks like you are describing objects that implement the IDisposable interface for C #. IDisposable has a Dispose () method, which when correctly defined on your own objects is used to free resources.

In addition, C # has destructors defined as such:

 public class Foo { public Foo() { // constructor } ~Foo() // destructor } 

when wrapping IDisposable objects in the used block, the Dispose () method is automatically called, another option is to drop it into the finally block (if not using ... using)

+1
source

The easiest way to do this is to include the guard object in the using statement. So something like this.

 using (sentry = new Sentry()) { //do your stuff here } 

After this block, the sentry will be released and taken out of the area.

+1
source

Source: https://habr.com/ru/post/1203308/


All Articles