473,785 Members | 2,746 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

IDisposable, using(), RAII and structs [Discussion]

Last night I had several thought about RAII and want to discuss a bit.

Why doesn't CSharp support destructors in structs? Wouldn't that make RAII
possible like in C++? When the struct goes out of scope, the dtor could be
immediately be called (no GC needed).

For that, you don't have to declare the whole File class as a struct (which
would be not good for performance when File has a lot of data-members).
Instead creating a thin wrapper would be a good solution:

public struct MyFile
{
File f;
public MyFile(string p) { f=new File(p); }
~MyFile() { f.Close(); }
}

That would do it.

I have a second though which got through my mind. What about introducing an
interface which is recognized by the compiler and forces usage of the
using() statement.

public interface IDisposableForc e : IDisposable{}

A second possibility could be declaring an attribute which marks
IDisposable-implementing-classes wheather using() should be mandatory or at
least suggested.

enum WarnLevel {NoWarn,WarnLvl 1,WarnLvl2,Warn Lvl3,WarnLvl4,G enerateError};

class UsingAttribute{ UsingAttribute( WarnLevel w){}}

[Using(WarnLvl3)] // that means if warnlevel 3 or higher is set a warning
is issued when this class is used without using()-statement
public class MyFile : File
{
public class MyFile(string p) :base(p){}
}

What do you think?

--
cody

[Freeware, Games and Humor]
www.deutronium.de.vu || www.deutronium.tk
Nov 15 '05 #1
28 2205
> For that, you don't have to declare the whole File class as a struct
(which
would be not good for performance when File has a lot of data-members).
Instead creating a thin wrapper would be a good solution:

public struct MyFile
{
File f;
public MyFile(string p) { f=new File(p); }
~MyFile() { f.Close(); }
}
Or you can just call f.Close(); yourself. Don't see the benefit here.
I have a second though which got through my mind. What about introducing an interface which is recognized by the compiler and forces usage of the
using() statement.

public interface IDisposableForc e : IDisposable{}

A second possibility could be declaring an attribute which marks
IDisposable-implementing-classes wheather using() should be mandatory or at least suggested.
using() is a C#-specific thing. It's just a try/finally and a call to
dispose at the end. using() just saves a few lines of code, that's all.
Nothing magical.
enum WarnLevel {NoWarn,WarnLvl 1,WarnLvl2,Warn Lvl3,WarnLvl4,G enerateError};

class UsingAttribute{ UsingAttribute( WarnLevel w){}}

[Using(WarnLvl3)] // that means if warnlevel 3 or higher is set a warning
is issued when this class is used without using()-statement
public class MyFile : File
{
public class MyFile(string p) :base(p){}
}


Any class that implements IDisposable should have it's Dispose method
(sometimes named Close) called. Simple as that. It's not too hard (check
to see if there's IDisposable, and if so, dispose it!).

-mike
MVP
Nov 15 '05 #2
I was just talking about something similar last week. What came out of it is
the notion of a helper class that can help detect cases where a user forgot
to Dispose/Close an object whose class implements IDisposable. The idea is
cause exceptions, throw up message boxes, or at least log these things, to
force people into proper coding form. I am putting this into practice in my
stuff.

It's not quite the same as constructs that are an explicit part of the
CLR/CTS or a particular language such as what you are suggesting, but IMO
it's a reasonable substitute in the absence of thsoe things. (Though for the
record I agree with another poster about the dubious nature of an
IDisposableForc e. I originally suggested that perhaps the system could
invoke an operator on a class whenever a reference is added or released,
which could allow classes to automatically perform their own disposal.)

"codymanix" <do************ *********@gmx.d e> wrote in message
news:eu******** ******@TK2MSFTN GP09.phx.gbl...
Last night I had several thought about RAII and want to discuss a bit.

Why doesn't CSharp support destructors in structs? Wouldn't that make RAII
possible like in C++? When the struct goes out of scope, the dtor could be
immediately be called (no GC needed).

For that, you don't have to declare the whole File class as a struct (which would be not good for performance when File has a lot of data-members).
Instead creating a thin wrapper would be a good solution:

public struct MyFile
{
File f;
public MyFile(string p) { f=new File(p); }
~MyFile() { f.Close(); }
}

That would do it.

I have a second though which got through my mind. What about introducing an interface which is recognized by the compiler and forces usage of the
using() statement.

public interface IDisposableForc e : IDisposable{}

A second possibility could be declaring an attribute which marks
IDisposable-implementing-classes wheather using() should be mandatory or at least suggested.

enum WarnLevel {NoWarn,WarnLvl 1,WarnLvl2,Warn Lvl3,WarnLvl4,G enerateError};

class UsingAttribute{ UsingAttribute( WarnLevel w){}}

[Using(WarnLvl3)] // that means if warnlevel 3 or higher is set a warning
is issued when this class is used without using()-statement
public class MyFile : File
{
public class MyFile(string p) :base(p){}
}

What do you think?

--
cody

[Freeware, Games and Humor]
www.deutronium.de.vu || www.deutronium.tk

Nov 15 '05 #3
Michael Giagnocavo [MVP] wrote:
For that, you don't have to declare the whole File class as a struct
(which would be not good for performance when File has a lot of
data-members).
Instead creating a thin wrapper would be a good solution:

public struct MyFile
{
File f;
public MyFile(string p) { f=new File(p); }
~MyFile() { f.Close(); }
}

Or you can just call f.Close(); yourself. Don't see the benefit here.


The benefit of and the idea behind RAII (resource acquisition is
initialization) is that it causes the cleanup code to be called
automatically upon exit, even when an exception is thrown earlier in the
function.

In my opinion, the absence of deterministic destruction, and hence the
impossibility of RAII, is something that Java and C# got totally wrong.

Gerhard Menzl
--
Replace "spambucket " with "kapsch" to reply
Nov 15 '05 #4

"Michael Giagnocavo [MVP]" <mg*******@Atre vido.net> wrote in message
news:%2******** **********@TK2M SFTNGP11.phx.gb l...
For that, you don't have to declare the whole File class as a struct

(which
would be not good for performance when File has a lot of data-members).
Instead creating a thin wrapper would be a good solution:

public struct MyFile
{
File f;
public MyFile(string p) { f=new File(p); }
~MyFile() { f.Close(); }
}


Or you can just call f.Close(); yourself. Don't see the benefit here.


Err... well, that's the whole point of RAII: you don't have to call
f.Close() yourself. The benefit is that when you don't have to call
f.Close() explicitely there is less room for you to make an error.

RAII is the single biggest thing I miss from C++ since I started working
with C#. It is scary to see all the sample code that uses unmanaged
resources sloppily. All these samples will end up creating armies of
programmers who deal sloppily with unmanaged resources, and these
programmers will create waves of applications that work unreliably.

A very typical code sample, from an ASP.NET application, is this:

private void BindData()
{
// Connect to the Database
SqlConnection myConnection = new SqlConnection(c onnection string);

// Retrieve the SQL query results and bind it to the Repeater
string SQL_QUERY = "SELECT ProductName, UnitPrice, UnitsInStock " +
"FROM Products";
SqlCommand myCommand = new SqlCommand(SQL_ QUERY, myConnection);

myConnection.Op en();
dgProducts.Data Source = myCommand.Execu teReader();
dgProducts.Data Bind();
myConnection.Cl ose();
}

What's wrong with this code? The problem is that if myCommand.Execu teReader
fails because e.g., a temporary network problem or any other reason and
throws an exception, then the connection will not be closed and it won't be
returned to the connection pool in a timely manner. Code like this will
result in a web app that will work unreliably under load and might start
failing when conditions are not ideal.

To make the code above robust, you'll want to wrap the usage of the
SqlConnection into a using-statement, which is the best we can do without
real RAII. I feel sorry for VB.NET programmers who don't have the using
keyword.

Sorry for the rant,
Sami

Nov 15 '05 #5
My thoughts exactly, Sami

Poorly written samples spawn poor code writers, since most of the "code
writers" simply cut and paste from other work instead of fully understanding
what is going on.

And yes, I see tons of ExecuteReader code not properly written to account
for a simple timeout or database exception. Hence they get connection
pooling at maximum exceptions and instead of trying to figure out why, they
just say "I need to increase the pool size"

....Amateurs...

--
Eric Newton
C#/ASP Application Developer
http://ensoft-software.com/
er**@cc.ensoft-software.com [remove the first "CC."]

PS: I run into many of these "cut and paste" coders in my career and I'm
wondering if its a sin to call them out?

"Sami Vaaraniemi" <sa************ ***@jippii.fi> wrote in message
news:bp******** **@phys-news1.kolumbus. fi...

"Michael Giagnocavo [MVP]" <mg*******@Atre vido.net> wrote in message
news:%2******** **********@TK2M SFTNGP11.phx.gb l...
For that, you don't have to declare the whole File class as a struct (which
would be not good for performance when File has a lot of data-members). Instead creating a thin wrapper would be a good solution:

public struct MyFile
{
File f;
public MyFile(string p) { f=new File(p); }
~MyFile() { f.Close(); }
}


Or you can just call f.Close(); yourself. Don't see the benefit here.


Err... well, that's the whole point of RAII: you don't have to call
f.Close() yourself. The benefit is that when you don't have to call
f.Close() explicitely there is less room for you to make an error.

RAII is the single biggest thing I miss from C++ since I started working
with C#. It is scary to see all the sample code that uses unmanaged
resources sloppily. All these samples will end up creating armies of
programmers who deal sloppily with unmanaged resources, and these
programmers will create waves of applications that work unreliably.

A very typical code sample, from an ASP.NET application, is this:

private void BindData()
{
// Connect to the Database
SqlConnection myConnection = new SqlConnection(c onnection string);

// Retrieve the SQL query results and bind it to the Repeater
string SQL_QUERY = "SELECT ProductName, UnitPrice, UnitsInStock " +
"FROM Products";
SqlCommand myCommand = new SqlCommand(SQL_ QUERY, myConnection);

myConnection.Op en();
dgProducts.Data Source = myCommand.Execu teReader();
dgProducts.Data Bind();
myConnection.Cl ose();
}

What's wrong with this code? The problem is that if

myCommand.Execu teReader fails because e.g., a temporary network problem or any other reason and
throws an exception, then the connection will not be closed and it won't be returned to the connection pool in a timely manner. Code like this will
result in a web app that will work unreliably under load and might start
failing when conditions are not ideal.

To make the code above robust, you'll want to wrap the usage of the
SqlConnection into a using-statement, which is the best we can do without
real RAII. I feel sorry for VB.NET programmers who don't have the using
keyword.

Sorry for the rant,
Sami

Nov 15 '05 #6
This is probably a good idea, perhaps a base class in the framework
"BaseRAII" that is either recognized by the compiler as a special class
[like the Debug class in System.Diagnost ics] or decorated with attributes to
warn of improper use.

In my mind the destructor of these BaseRAII classes should always be called
to release the resource immediately.

--
Eric Newton
C#/ASP Application Developer
http://ensoft-software.com/
er**@cc.ensoft-software.com [remove the first "CC."]

"Ted Miller" <te*@nwlink.com > wrote in message
news:vs******** ****@corp.super news.com...
I was just talking about something similar last week. What came out of it is the notion of a helper class that can help detect cases where a user forgot to Dispose/Close an object whose class implements IDisposable. The idea is
cause exceptions, throw up message boxes, or at least log these things, to
force people into proper coding form. I am putting this into practice in my stuff.

It's not quite the same as constructs that are an explicit part of the
CLR/CTS or a particular language such as what you are suggesting, but IMO
it's a reasonable substitute in the absence of thsoe things. (Though for the record I agree with another poster about the dubious nature of an
IDisposableForc e. I originally suggested that perhaps the system could
invoke an operator on a class whenever a reference is added or released,
which could allow classes to automatically perform their own disposal.)

"codymanix" <do************ *********@gmx.d e> wrote in message
news:eu******** ******@TK2MSFTN GP09.phx.gbl...
Last night I had several thought about RAII and want to discuss a bit.

Why doesn't CSharp support destructors in structs? Wouldn't that make RAII possible like in C++? When the struct goes out of scope, the dtor could be immediately be called (no GC needed).

For that, you don't have to declare the whole File class as a struct

(which
would be not good for performance when File has a lot of data-members).
Instead creating a thin wrapper would be a good solution:

public struct MyFile
{
File f;
public MyFile(string p) { f=new File(p); }
~MyFile() { f.Close(); }
}

That would do it.

I have a second though which got through my mind. What about introducing

an
interface which is recognized by the compiler and forces usage of the
using() statement.

public interface IDisposableForc e : IDisposable{}

A second possibility could be declaring an attribute which marks
IDisposable-implementing-classes wheather using() should be mandatory or

at
least suggested.

enum WarnLevel {NoWarn,WarnLvl 1,WarnLvl2,Warn Lvl3,WarnLvl4,G enerateError};
class UsingAttribute{ UsingAttribute( WarnLevel w){}}

[Using(WarnLvl3)] // that means if warnlevel 3 or higher is set a warning is issued when this class is used without using()-statement
public class MyFile : File
{
public class MyFile(string p) :base(p){}
}

What do you think?

--
cody

[Freeware, Games and Humor]
www.deutronium.de.vu || www.deutronium.tk


Nov 15 '05 #7
"codymanix" <do************ *********@gmx.d e> wrote in message <news:eu******* *******@TK2MSFT NGP09.phx.gbl>. ..
Last night I had several thought about RAII and want to discuss a bit.

Why doesn't CSharp support destructors in structs? Wouldn't that make RAII
possible like in C++? When the struct goes out of scope, the dtor could be
immediately be called (no GC needed).

For that, you don't have to declare the whole File class as a struct (which
would be not good for performance when File has a lot of data-members).
Instead creating a thin wrapper would be a good solution:

public struct MyFile
{
File f;
public MyFile(string p) { f=new File(p); }
~MyFile() { f.Close(); }
}

That would do it.
This would be tantamount to admitting that castrating Visual Basic
was a mistake and, therefore, must be considered unnecessary and
"looking backwards" instead of Looking Towards The Future. You
might as well argue for the reintroduction of reference counting!
I have a second though which got through my mind. What about introducing an
interface which is recognized by the compiler and forces usage of the
using() statement.

public interface IDisposableForc e : IDisposable{}

A second possibility could be declaring an attribute which marks
IDisposable-implementing-classes wheather using() should be mandatory or at
least suggested.

enum WarnLevel {NoWarn,WarnLvl 1,WarnLvl2,Warn Lvl3,WarnLvl4,G enerateError};

class UsingAttribute{ UsingAttribute( WarnLevel w){}}

[Using(WarnLvl3)] // that means if warnlevel 3 or higher is set a warning
is issued when this class is used without using()-statement
public class MyFile : File
{
public class MyFile(string p) :base(p){}
}

What do you think?


If you want real destructors, use C++ or Visual FoxPro. Get over it!
Anyway, what happens when (not if) existing classes are changed to
implement IDisposableForc e in addition to or instead of IDisposable?
Do you force everyone to go back and rewrite their code? Oh wait, this
has already been done to Visual Basic, so it must be OK. Never mind...

--
Joe Foster <mailto:jlfoste r%40znet.com> DC8s in Spaace: <http://www.xenu.net/>
WARNING: I cannot be held responsible for the above They're coming to
because my cats have apparently learned to type. take me away, ha ha!
Nov 15 '05 #8
"Joe "Nuke Me Xemu" Foster" <jo*@bftsi0.UUC P> wrote in message
news:uk******** ******@TK2MSFTN GP11.phx.gbl...
This would be tantamount to admitting that castrating Visual Basic
was a mistake and, therefore, must be considered unnecessary and
"looking backwards" instead of Looking Towards The Future. You
might as well argue for the reintroduction of reference counting!
Actually, I sorta do argue for the reintroduction of refcounting -- but not
for lifetime control. I think there should be a 'reference' operator,
because (I believe) the system (compiler and runtime) know when references
are added and removed from an object; this would allow an object to use a
sort of refcounting scheme to implement auto destruction.
If you want real destructors, use C++ or Visual FoxPro. Get over it!
If you want to target the CLR (i.e., if you want to program for .Net), this
is not possible. (Managed C++ destructors have similar semantics to C#
destructors.)
Anyway, what happens when (not if) existing classes are changed to
implement IDisposableForc e in addition to or instead of IDisposable?
Do you force everyone to go back and rewrite their code? Oh wait, this
has already been done to Visual Basic, so it must be OK. Never mind...


This isn't so sifferent from the notion of breaking binary compatibility
that existed in earlier versions of VB. There's an interface contract, and
changing it requires changes to consumers of the class, just as it always
has.
Nov 15 '05 #9
> Actually, I sorta do argue for the reintroduction of refcounting -- but
not
for lifetime control. I think there should be a 'reference' operator,
because (I believe) the system (compiler and runtime) know when references
are added and removed from an object; this would allow an object to use a
sort of refcounting scheme to implement auto destruction.

The compiler knows it when references are added or released. Reference
counting would be fine for some classes that:
- Does not contain References of reference-counted types (to avoid situation
where objects references each other but nowbody can reach them)
- That aren't copied and passed much (Sorting an array of reference counted
objects would be very slow since each swap involves lots of decrementing
and incrementing the reference count)

If structs would be allowed to have dtors, reference counting could simply
be implemented by developers.

--
cody

[Freeware, Games and Humor]
www.deutronium.de.vu || www.deutronium.tk
Nov 15 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

26
448
by: codymanix | last post by:
Last night I had several thought about RAII and want to discuss a bit. Why doesn't CSharp support destructors in structs? Wouldn't that make RAII possible like in C++? When the struct goes out of scope, the dtor could be immediately be called (no GC needed). For that, you don't have to declare the whole File class as a struct (which would be not good for performance when File has a lot of data-members). Instead creating a thin wrapper...
0
9480
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10147
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
10087
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9947
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8971
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6737
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5511
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4046
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
2877
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.