Why is there no RAII in .NET?

Being primarily a C ++ developer, the lack of RAII (Initialization of Resource Acquisition) in Java and .NET has always bothered me. The fact that the cleaning burden is transferred from the author of the class to its consumer (using try finally or .NET using construct ) seems to be noticeably inferior.

I see why in Java there is no support for RAII, since all objects are on the heap, and the garbage collector does not in fact support deterministic destruction, and in .NET with the introduction of value types ( struct ) we have (apparently) an ideal candidate for RAII. The value type created on the stack has a well-defined area and you can use the C ++ destructor semantics. However, the CLR does not allow a value type to have a destructor.

My random searches found one argument that if the type of value is boxed , it falls under the jurisdiction of the garbage collector, and therefore its destruction becomes non-deterministic. I believe that this argument is not strong enough, the benefits of RAII are large enough to say that a value type with a destructor cannot be placed in a box (or used as a member of a class).

To shorten the long story, my question is : are there any other types of reason values ​​that cannot be used to implement RAII in .NET? (or do you think my argument about the obvious benefits of RAII is wrong?)

Edit: I must not have formulated the question clearly, since the first four answers missed the point. I know about Finalize and its non-deterministic characteristics, I know about the using construct, and I feel that these two options are inferior to RAII. using is another thing the class consumer should remember (how many people forgot to put StreamReader in the using block?). My question is a philosophical question about language design, why can it be improved in this way?

For example, using a generic deterministically destructible value type, I can make using and lock keywords redundant (reachable library classes):

  public struct Disposer<T> where T : IDisposable { T val; public Disposer(T t) { val = t; } public T Value { get { return val; } } ~Disposer() // Currently illegal { if (val != default(T)) val.Dispose(); } } 



I cannot help but end with the quote I once saw, but I cannot find its origin.

You can accept my determinate destruction when my cold dead hand goes out of scope. --Anon

+62
struct destructor value-type raii
Oct 06 '08 at 9:25
source share
7 answers

The best heading would be "Why isn't RAII in C # / VB". C ++ / CLI (the evolution of abortion controlled by C ++) has RAII in the same sense as C ++. This is just the sugar syntax for the same finalization template as the rest of the CLI languages ​​(destructors in managed objects for C ++ / CLI are actually finalists), but there is one.

You may like http://blogs.msdn.com/hsutter/archive/2004/07/31/203137.aspx

+15
Oct 06 '08 at 10:48
source share

Great question and one that really bothered me. The benefits of RAII seem to be perceived very differently. In my experience with .NET, the lack of a deterministic (or at least reliable) resource collection is one of the main weaknesses. In fact, .NET has forced me to use entire architectures several times to work with unmanaged resources, which may (but not necessarily) require an explicit collection. This, of course, is a huge flaw, because it complicates the overall architecture and directs the client's attention to more central aspects.

+13
Oct 06 '08 at 9:44
source share

Brian Harry has a good reasoning article here .

Here is an excerpt:

What about deterministic finalization and value types (structs)?

-------------- I saw a lot of questions about structures having destructors, etc. It is worth the comment. There are many questions about why some languages ​​do not have them.

(1) composition β€” they do not give you a determined lifetime in the general case for the same types of composition, the reasons described above. Any non-deterministic class containing one will not call the destructor until it has been finalized by the GC.

(2) copy constructors - one place where it would be really nice to have a stack of allocated places. They will be brought to the method, and everything will be Great. Unfortunately, to get this working, you also need to add copy constructors and call them every time the instance is copied. This is one of the ugliest and most complex things about C ++. You end up getting code executed in everything where you don't expect it. This causes bundles of language problems. Some language designers have chosen to avoid this.

Let's say we created structures with destructors, but added a bunch of restrictions for their behavior reasonable in the face of the problems above. Limitations will be something like:

(1) You can only declare them as local variables.

(2) You can only transmit them as-is.

(3) You cannot assign them, you can only access fields and call methods on them.

(4) You cannot insert them.

(5) Problems associated with their use Reflection (late binding), because it usually involves boxing.

maybe more, but it's a good start.

What will these things be? Would you actually create a file or database connection class that can ONLY be used as a local variable? I do not believe that someone really will. Instead, you should create a general-purpose connection, and then create an automatic destroyed shell to use as a localized local variable. the caller could choose what they wanted to use. Note that the calling solution is not completely encapsulated in the object itself. Considering that you can use something as sentences arising in a couple of sections.

Replacing RAII in .NET is a usage pattern that works almost the same way once you get used to it.

+12
Oct. 06 '08 at 9:57
source share

Closest you will get to this very limited stackalloc statement.

+1
Oct 06 '08 at 9:27 a.m.
source share

There are several similar threads if you are looking for them, but basically it comes down to the fact that if you want RAII on .NET to simply implement the IDisposable type and use the using statement to get deterministic deletion. Thus, many of the same ideals can be realized and used only a little more verbose.

+1
Oct. 06 '08 at 9:32
source share

IMHO, the big things VB.net and C # need:

  1. "use" declarations for fields, which will cause the compiler to generate code to remove all fields marked in this way. The default behavior should be for the compiler to make the implementation of the IDisposable class if it has not done so, or insert the removal logic before starting the main disposal procedure for any of several common IDisposal implementation templates, or use the attribute to indicate that burial things should run in a routine with a specific name.
  2. deterministic removal of objects, constructors and / or field initializers generate an exception either by default (calling the default delete method) or user behavior (calling a method with a specific name).
  3. For vb.net, an automatically generated method to remove all WithEvent fields.

    All of them can be pretty well removed in vb.net, and in C # a little worse, but first-class support for them will improve both languages.

+1
Dec 14 '10 at 4:16
source share

You can make RAII form in .net and java using finalize () methods. The overload of finalize () is called before the class is cleared by the GC and therefore can be used to clean up any resources that should not be saved by the class (mutexes, sockets, file descriptors, etc.). Nevertheless, it is still not deterministic.

With .NET, you can do some of this deterministically using the IDisposable interface and the using keyword, but this has limitations (using the construct when it is used for deterministic behavior, there is still no deterministic memory deallocation, it is not used automatically in classes and etc.).

And yes, I believe that RAII ideas should be implemented in .NET and other managed languages, although the exact mechanism can be discussed endlessly. The only alternative that I could see would be to introduce a GC that could handle arbitrary resource cleansing (not just memory), but then you have problems when the specified resources must be necessarily released.

-3
Oct 06 '08 at 9:31
source share



All Articles