Replies: 14 comments
-
I like try using (var v = new Resource ())
{
}
catch (Exception e)
{
}
finally
{
} This still uses the term |
Beta Was this translation helpful? Give feedback.
-
You can only manage a single resource per using (var v = new Resource())
try
{
}
catch (Exception e)
{
}
finally
{
} |
Beta Was this translation helpful? Give feedback.
-
You use the syntax that already exists for try using (Font font3 = new Font("Arial", 10.0f),
font4 = new Font("Arial", 10.0f))
{
// Use font3 and font4.
} An alternative would be to allow using (var mydisposable = ...)
{
}
catch ( ...) // optional
{
}
finally { ... } // optional
// implicit finally that dispose the resources We will need to think about the scope of the |
Beta Was this translation helpful? Give feedback.
-
Okay but I'm still wondering why this proposal is worth the work and added complexity over what we have today:
Is it really so much of a gain to lose the |
Beta Was this translation helpful? Give feedback.
-
That would force I largely agree with @jnm2, we can achieve this functionality with the syntax we have today. A single additional keyword is not overly verbose. But I also wouldn't mind Java's TWR syntax of specifying resources immediately after |
Beta Was this translation helpful? Give feedback.
-
Whatever the LDM decides should accomplish the following goals: 1- Simpler syntax with less nested { } 2- Avoid requiring the declaration of variables prior to the 3- Avoid the abuse of the A fair amount of code e.g. in multithreaded programming implements |
Beta Was this translation helpful? Give feedback.
-
I don't want to discuss this here because there's already a conversation in another thread, but using IDisposable for arbitrary scoping is not abuse. |
Beta Was this translation helpful? Give feedback.
-
@jnm2 It is a bit of an ideological debate. This said, I wish there were a simpler way to do deterministic scoping / transactions e.g.
|
Beta Was this translation helpful? Give feedback.
-
I don't think I've ever had this experience, and I'm one of the more- shall we say, creative- IDisposable users. Do you know of an example of real-world ambiguity here? |
Beta Was this translation helpful? Give feedback.
-
I don't know about number two here. It may look be confusing. |
Beta Was this translation helpful? Give feedback.
-
Instead of this I would prefer something like defer in golang that would run code after scope ends to avoid nesting. It would have much more wide range usage scenarios, not just for Dispose. Maybe something like
|
Beta Was this translation helpful? Give feedback.
-
Let me summarize the problems discussed above (and related issues) very explicitly, so that we could discuss:
void Foo()
{
var fs = File.Create(path);
// use fs
fs.Close(); // never called in case of an exception
} instead of using (FileStream fs = File.Create(path))
{
}
{
var fs =
try
{
\\ use fs
}
finally
{
if (fs != null)
((IDisposable)fs).Dispose();
}
} There is no
Common bug - forgetting the null check in the finally block. Minor issue - some Disposable objects implement the interface explicitly, thus either a cast is required or a call to The cleanest alternative syntax (as discussed above) is indeed using (var v = new Resource(), ...)
try
{
}
catch (Exception e)
{
}
finally
{
} but that is essentially a It also does not protect against exceptions in the resource's construction. To do that, one must write: try
{
using(resource)
{
//Do something here
}
} catch(Exception)
{
//Handle Error
} which is verbose.
public class Stuff : IDisposable
{
// some fields that require cleanup
private bool disposed = false; // to detect redundant calls
public void Dispose()
{
Dispose(true);
GC.SupressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// Dispose managed resources.
}
// There are no unmanaged resources to release, but
// if we add them, they need to be released here.
}
disposed = true;
// If it is available, make the call to the
// base class's Dispose(Boolean) method
base.Dispose(disposing);
}
} The implementation can be trickier if a finalizer is required: https://www.codeproject.com/Articles/15360/Implementing-IDisposable-and-the-Dispose-Pattern-P noting that implementing a finalizer can have drastic impact on GC performance. Common problem: every entry point into the class needs a guard to check whether or not the object has been disposed.
Taking the examples from another thread, private void FiddleTheFrobble()
{
this.Frobble.Unlock();
try
{
Foo(); // Can throw
this.Frobble.Fiddle(); // Can throw
Bar(); // Can throw
}
finally
{
this.Frobble.Lock();
}
} is often rewritten as private void FiddleTheFrobble()
{
using (var janitor = new FrobbleJanitor(this.Frobble))
{
Foo(); // Can throw
this.Frobble.Fiddle(); // Can throw
Bar(); // Can throw
}
} where FrobbleJanitor looks roughly like class FrobbleJanitor : IDisposable
{
private Frobble frobble;
public FrobbleJanitor(Frobble frobble)
{
this.frobble = frobble;
this.frobble.Unlock();
}
public void Dispose()
{
this.frobble.Lock();
}
} which is verbose and splits the handling of
var myHTML = new HTML();
myHTML.InsertStartTag();
// ...
myHTML.InsertEndTag(); becomes the verbose HTML myHTML; // refactoring: declaration outside of the block; explicit type declaration, not var
try {
myHTML = new HTML(); // separate call to the constructor
myHTML.InsertStartTag();
// ...
}
catch(Exception)
{
// ...
}
finally
{
if (myHTML != null)
myHTML.InsertEndTag();
} |
Beta Was this translation helpful? Give feedback.
-
@john-cd public class Stuff : IDisposable
{
// some fields that require cleanup
private bool isDisposed = false; // to detect redundant calls
public virtual void Dispose()
{
if (isDisposed) return;
isDisposed = true;
// Dispose managed resources, including SafeHandles which are managed resources and encapsulate their own finalizer and unmanaged resources
}
} |
Beta Was this translation helpful? Give feedback.
-
I came here after I finally (har, har) got to use Java 7 on an Android project (phew, made it to 2011! Moved min SDK to 19 from 15) and got rid of my finally blocks for try with resources. I thought, dang, it looks like Java has using with catch blocks, why not C#? Then I saw the comments here, particularly @jnm2 suggesting: using (var v = new Resource())
try
{
}
catch (Exception e)
{
}
finally
{
} I guess the only inhibition is the compiler is nesting try/finally in a try/catch[/finally], but source code doesn't necessarily look like that, so maybe I just turn a blind eye? Also, Java try with resources can't put multiple resources in a single try ( ) like using can, and each try appears to require its own set of { } while using does not. If something elegant can massage catching exceptions while using a using block, great. But this thread helped me conclude that Java's implementation isn't really better. Score: Java 0, C# 1,000,000. |
Beta Was this translation helpful? Give feedback.
-
Be able to use a try/catch/finally block like a using statement in c#
Example C#:
ex.AddSuppressed(exceptionFromDispose)
orex.Data["SuppressedException"] = exceptionFromDispose;
Beta Was this translation helpful? Give feedback.
All reactions