|
thanks
|
|
|
|
|
I understand the answer is "yes" as compared to just instantiating objects and never disposing, clearing, or closing them.
But those two are not the only alternatives.
"using" get compiled as try-finally anyway. (See using statement - C# Reference | Microsoft Docs[^] )
However, if you use try-catch-finally, you achieve the same results (calling Dispose in the finally block), but can gain benefits.
1 - Capture of runtime data for troubleshooting. If you specify the catch block, you can add name-value pairs for runtime values to the Exception.Data collection. Logging can then pull these values out when the exception is logged, wherever you choose on the stack.
2 - When troubleshooting in the IDE, you can step through the "cleanup" in catch and finally, which you cannot do with the "using" statement. This reduces initial development time and troubleshooting time.
3 - You have full control over the order and operations of releasing resources. Not all objects inherit IDisposable. In addition, a given object may have child objects or other objects in a collection that need to be separately disposed of (think .Clear()). Using the finally block, you have control over how objects are cleaned up, and if any logging is needed.
The downside is that using try-catch-finally takes a little more coding time upfront. However, most of that should be copy-and-paste. Doing so will, in the aggregate, also save you a little time, so it should balance out, leaving you with better, less buggy, code.
IMHO, if I create an object, I should clean it up and not leave that to chance or the hope that under the covers, MS got the "using" statement right.
That said, what are your views on using the "using" statement?
|
|
|
|
|
Consider multiple using blocks - would you really prefer the try..finally version?
using (SqlConnection connection = new SqlConnection("..."))
using (SqlCommand command = new SqlCommand("...", connection))
{
...
using (SqlDataReader reader = command.ExecuteReader())
{
...
}
} vs:
{
SqlConnection connection = new SqlConnection("...");
try
{
{
SqlCommand command = new SqlCommand("...", connection);
try
{
...
{
SqlDataReader reader = command.ExecuteReader();
try
{
...
}
finally
{
if (reader != null)
((IDisposable)reader).Dispose();
}
}
}
finally
{
if (command != null)
((IDisposable)command).Dispose();
}
}
}
finally
{
if (connection != null)
((IDisposable)connection).Dispose();
}
}
MSBassSinger wrote: 1 - Capture of runtime data for troubleshooting.
There's nothing stopping you from putting a try..catch block either inside or outside of your using block. You can still add any extra data to the exception as required.
MSBassSinger wrote: 3 - You have full control over the order and operations of releasing resources.
Disposable objects should be responsible for cleaning up their own resources. It shouldn't be up to the caller to know that they need to clean up a child collection before calling Dispose .
MSBassSinger wrote: the hope that under the covers, MS got the "using" statement right.
It's been around for almost two decades. If they hadn't got it right, then you'd have heard about it by now.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Yes, even more so I would avoid the using statement. However, your alternative code is nothing like what I would write. No need for the nested try-finally blocks.
Quote: There's nothing stopping you from putting a try..catch block either inside or outside of your using block. You can still add any extra data to the exception as required.
Then why bother with the using statements? They are redundant.
Quote: Disposable objects should be responsible for cleaning up their own resources. It shouldn't be up to the caller to know that they need to clean up a child collection before calling Dispose.
As I said, not all objects that utilize resources inherit IDisposable. They *should*, and when they do, they *should* completely clean up their resources. By having a consistent practice of not using the using statement and coding the try-catch-finally blocks, I have better step-through debugging and better control over cleaning up my resources for when those edge case situations occur.
I am not saying it is "wrong" to use the using statement. I am merely saying why, after years of experience, I choose not to use it.
I appreciate that you responded, and it does go to the point of understanding why others do choose to use the using statement.
|
|
|
|
|
MSBassSinger wrote: No need for the nested try-finally blocks.
Without them, you can easily introduce bugs where resources don't get cleaned up.
For example:
SqlConnection connection = new SqlConnection("...");
SqlCommand command = new SqlCommand("...", connection);
try
{
...
}
finally
{
if (command != null) ((IDisposable)command).Dispose();
if (connection != null) ((IDisposable)connection).Dispose();
} If the SqlCommand ctor throws an exception, the SqlConnection is never cleaned up.
To do it properly, you would need something like:
SqlConnection connection = null;
SqlCommand command = null;
try
{
connection = new SqlConnection("...");
command = new SqlCommand("...", connection);
...
}
finally
{
if (command != null) ((IDisposable)command).Dispose();
if (connection != null) ((IDisposable)connection).Dispose();
} It's quite a lot of boilerplate and ceremony that the developer needs to get just right to make it work as well as a couple of using blocks.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Quote: Without them, you can easily introduce bugs where resources don't get cleaned up.
Example #1 is something only a novice would do, and novices have manifold ways of introducing bugs. Your 2nd example is exactly what I do - no bugs introduced. And in that example, it only adds two lines of code.
So yes, I much prefer the 2nd example over the using statement(s) for the flexibility I described in the OP. And it doesn't slow me down. After all, coding is only a fraction of the time wed spend doing software development.
|
|
|
|
|
As with every other tool in the box, you must know what it's doing in the background for you, since it is just syntactic sugar, and how to use it properly.
A using block should be used where appropriate. If you don't care about your items 1, 2, and 3 for a certain block of code, then a using block is just fine.
|
|
|
|
|
Quote: A using block should be used where appropriate
Where would you consider appropriate?
Thanks for taking time to respond.
|
|
|
|
|
Again, If you don't care about your items 1, 2, and 3 for a certain block of code, then a using block is just fine.
If I build a SqlConnection and SqlCommand, do I really care about your list of items? Nope. I'm going to concerned with just two things. Any exceptions thrown by the Command and the data returned. That's scoped to the inside of the using block. The method this block is in is either going to let the exception bubble up or it's going to return data. Nothing more.
|
|
|
|
|
Quote: I'm going to concerned with just two things. Any exceptions thrown by the Command and the data returned.
I understand and agree with what you say. But, I look for more. When something does go wrong in production, I'd like the debug log to have captured the runtime values of what I was using in the SqlConnection and SqlCommand object. With those, I can quickly tell if there was something wrong with the values (e.g. did someone diddle with a config file that had connection info?). Or maybe some of my query parameter values were unexpected. In any case, by having captured them in a catch block, I spend 5 minutes on solving a problem, instead of an hour or more guessing at what might have caused it. I could embed a try-catch within the using statement (not sure if the instantiation portion of the using statement would get "caught" in the catch block, though), but then if I have the try-catch, why not just add finally and do away with the redundancy of the using statement?
If the values seem OK, with the try-catch-finally, I can step through all the code, which is limited with the using statement.
I understand if these things are not valuable to you. But they are to me after many years of running into the odd issues that could have been solved by a couple more lines of code. Every developer has to pick and chose what they consider valuable to them, as well as to a customer.
|
|
|
|
|
Again, if you want that flexibility, don't us a using .
I don't have a need for the "what if" situation you posted, so I could easily just go with a using and not worry about it crashing under circumstances that were unexpected.
If I need to consider that the values are critical and need to be checked out in the future, I can always wrap it some logging code, or implement the using my self.
You're answering your own question.
|
|
|
|
|
I have to agree with Richard - using is cleaner, clearer, and easier to use.
And ... it makes the scope of the variable very, very obvious which a try...finally block doesn't - when you use the try...finally version, the scope of the variable is the block which contains the try...finally code (or it wouldn't be available for Dispose in the finally block) so you could write code to use a variable after it's content is Disposed:
SqlCommand cmd = new SqlCommand(sql, con);
try
{
...
}
finally
{
if (cmd != null) cmd.Dispose();
}
cmd.ExecuteNonQuery();
using (SqlCommand cmd = new SqlCommand(sql, con))
{
...
}
cmd.ExecuteNonQuery();
Sent from my Amstrad PC 1640
Never throw anything away, Griff
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Quote: And ... it makes the scope of the variable very, very obvious which a try...finally block doesn't
Looks pretty obvious to me.
First, I would make the declaration statement as:
SqlCommand cmd = null;
since I would want the instantiation within the try block.
Your second example would be caught in the IDE, before you even tried to compile.
I agree that Quote: using is cleaner, clearer, and easier to use.
But easier does not always lead to better, more reliable, or less buggy. For the small amount of extra effort to use try-catch-finally, it seems to me to be worth the effort. I've run into objects created via the using statement that left me with odd behavior that could not be stepped through in a using statement. But once I did away with the using statement, and used try-catch-finally, I found the problem and corrected it within minutes. So to avoid these unnecessary, but rare issues, I don't take shortcuts like the using statement. I realize the responsibility is 100% on me to cleanup the objects I create, and I am OK with that.
Thanks, though, for taking the time to explain why you use it.
|
|
|
|
|
Quote: Your second example would be caught in the IDE, before you even tried to compile.
Precisely - you do realise that VS does a partial compilation while you type I assume - so it's caught before run time, which is always better from reliability and maintainability POV.
Sent from my Amstrad PC 1640
Never throw anything away, Griff
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Quote: you do realise that VS does a partial compilation while you type I assume
Of course. Even the VB IDE did that back in the days before .NET. I was referring to when you would compile the project, not what the IDE was doing in the background, which is why the UI can tell you there is a problem.
|
|
|
|
|
MSBassSinger wrote: But easier does not always lead to better, more reliable, or less buggy. For the small amount of extra effort to use try-catch-finally, it seems to me to be worth the effort. I've run into objects created via the using statement that left me with odd behavior that could not be stepped through in a using statement. But once I did away with the using statement, and used try-catch-finally, I found the problem and corrected it within minutes. So to avoid these unnecessary, but rare issues, I don't take shortcuts like the using statement. I realize the responsibility is 100% on me to cleanup the objects I create, and I am OK with that.
Then don't use a using . It's your preference.
You seem to be looking for someone to refute your case for avoiding using . That's not going to happen.
|
|
|
|
|
The folks who responded so far have given some good insight as to why they use the using statement. I appreciate that they took the time to engage in a conversation about the topic. I understand those who do use it a bit better now.
I want to make it clear that although I would rarely choose to use it, that is my choice in the environments and contexts that I work in. I am in no place to judge someone else's choice, and I do not intend to imply that by this thread.
|
|
|
|
|
I tend to agree; though I'm drawn to using "using" because it makes me think harder when I have streams consuming streams that consume other streams (serializing, deserializing, encrypting, decrypting, compressing, uncompressing, xml versus binary, ...); using streaming "components" / iterators.
"Finally", is so ... "final".
(Also, "some" use try ... catch (nothing) as a crutch for sloppy thinking / coding).
At least, "using" is a useful thought experiment.
The Master said, 'Am I indeed possessed of knowledge? I am not knowing. But if a mean person, who appears quite empty-like, ask anything of me, I set it forth from one end to the other, and exhaust it.'
― Confucian Analects
modified 31-Jul-19 10:39am.
|
|
|
|
|
capture the screenshot of desktop using C#
|
|
|
|
|
Google is your friend: Be nice and visit him often. He can answer questions a lot more quickly than posting them here...
A very quick search using your question as the search term gave over 300,000 hits, including SO, MSDN, YouTube, CP, and a pile of other sites: capture the screenshot of desktop using C# - Google Search[^]
In future, please try to do at least basic research yourself, and not waste your time or ours.
Sent from my Amstrad PC 1640
Never throw anything away, Griff
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
I came of think of this, I wrote an application quite a while ago that did the same thing using .NET framework, I think I used System.Drawing to capture the graphics from the screen—maybe something else, please see there.
Here is the complete sample of this project, Windows Saving a screenshot using C# sample in C# for Visual Studio 2013
The sh*t I complain about
It's like there ain't a cloud in the sky and it's raining out - Eminem
~! Firewall !~
|
|
|
|
|
Hello everyone,
I am actually trying to create or generate automatically struct using the class "TypeBuilder".
I have already found a solution to create an "enum".
Here is the Code that I found as example on the microsoft-page:
using System.Reflection;
using System.Reflection.Emit;
namespace IoddParser
{
class test{
public void CreateEnum()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
AssemblyName aName = new AssemblyName("TempAssembly");
AssemblyBuilder ab = currentDomain.DefineDynamicAssembly(
aName, AssemblyBuilderAccess.RunAndSave);
ModuleBuilder mb = ab.DefineDynamicModule(aName.Name, aName.Name + ".dll");
EnumBuilder eb = mb.DefineEnum("Elevation", TypeAttributes.Public, typeof(int));
eb.DefineLiteral("Low", 0);
eb.DefineLiteral("High", 1);
Type finished = eb.CreateType();
ab.Save(aName.Name + ".dll");
foreach(object o in Enum.GetValues(finished) )
{
Console.WriteLine("{0}.{1} = {2}", finished, o, ((int) o));
}
}
How can I do the same procedure to get a struct (NOT A CLASS )
Thank you.
|
|
|
|
|
|
Because of the constraints that make using instances of run-time defined Types difficult, I'd recommend you look at an alternative like System.Dynamic ExpandoObject.
You create a Struct on-the-fly: any instance of it is going to be boxed, and right there you may have lost the potential benefits of using a Struct.
The few cases I've seen that needed to cook up some run-time bag of mixed Types could all be handled using System.Dynamic (or, even the now deprecated 'ArrayList).
Rick Strahl has done some very interesting work with ExpandoObject that I think could be relevant to your concerns: [^].
Describe your use case in detail, maybe you'll get more specific feedback.
«Where is the Life we have lost in living? Where is the wisdom we have lost in knowledge? Where is the knowledge we have lost in information?» T. S. Elliot
modified 1-Aug-19 14:45pm.
|
|
|
|
|
BillWoodruff wrote: or, even the now deprecated ArrayList
I'm not sure you'd ever need to use ArrayList , when you could just use List<object> instead.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|