C# using Statement equivalent in Swift - c#

I'm very new to Swift language, I have a C# Background.
and I'm wondering if there is an equivalent code for C# using statement in swift Language
using( var a = new MyClass()){
//Code Here
}

Swift's automatic reference counting guarantees deterministic deinitalization (unlike the CLR's garbage collector), so you can put clean up code in your class' deinit method. This is exactly like RAII in C++. This technique works even if an exception is thrown.
class MyClass() {
var db = openDBConnection() //example resource
deinit() {
db.close()
}
}
func foo() {
var a = MyClass()
print(a) // do stuff with a
// the (only) reference, a, will go out of scope,
// thus the instance will be deinitialized.
}
You can also use a defer statement:
var a = MyClass()
defer { a.cleanUp() /* cleanup a however you wish */ }
You lose the standardization of using an Interface like IDisposable, but you gain generality in being able to execute whatever code you wish.

Just learning Swift and came up with the same question.
The closest I could get was this:
if let UOW = (try UnitOfWork() as UnitOfWork?)
{
}
It's a bit of a hack on optional binding but seems to work. You will need to make sure your class has a deinit defined as called out above by Alexander. I found that even if my init throws an exception, the deinit method is still called as soon as you go out of scope on the IF statement.
NOTE: Make sure you are using weak references if applicable to make sure your deinit actually gets called!
It is probably more Swifty to use a DO block for your scoping:
do
{
let UOW = try UnitOfWork()
// your code here
}
Which has the benefit of avoiding a "pyramid of doom" with your pseudo using blocks (like you'll get in c#)

Related

Is IDisposable object disposed itself after RETURN from method?

Let's say, I have the following code:
theIDisposableObject myMethod()
{
theIDisposableObject smth=new theIDisposableObject();
return smth;
}
void Main()
{
var A= myMethod();
...
A.Dispose();
}
Do I do it correctly? i mean, is smth disposed on itself, because it is referred to by A variable (which is being disposed), or even smth needs its own disposal (if so, only with using is the solution)?
Is the object disposed? Yes.
Is there a better way? Yes. Use the using statement.
AnIDisposableObject myMethod()
{
AnIDisposableObject smth=new AnIDisposableObject();
return smth;
}
(...)
using( var a = myMethod())
{
}
// a is disposed here.
This is important because if an exception is thrown between var A= myMethod(); and A.Dispose(); A would not be disposed. Bad.
C#8
In C#8
things get even easier.
if (...)
{
using FileStream f = new FileStream(#"C:\users\jaredpar\using.md");
// statements
}
// Equivalent to
if (...)
{
using (FileStream f = new FileStream(#"C:\users\jaredpar\using.md"))
{
// statements
}
}
The lifetime of a using local will extend to the end of the scope in which it is declared. The using locals will then be disposed in the reverse order in which they are declared.
{
using var f1 = new FileStream("...");
using var f2 = new FileStream("..."), f3 = new FileStream("...");
...
// Dispose f3
// Dispose f2
// Dispose f1
}
Is it Disposesd? In most cases yes.
The code you showed us makes no sense. There has to be something else between the function call and the Dispose call to even consider writing it like this. And those can all throw exceptions, casually skipping over dispose.
I have one rule for IDisposeables:
Never split up the creation and disposing of a IDisposeable across multiple pieces of code. Create. Use. Dispose. All in the same piece of code, ideally using a Using Block. Everything else is just inviting problems.
The rare exception is when you wrap around something Disposeable. In that case you implement iDisposeable for the sole purpose of relaying the Dispose call to the contained instance. That is btw. the reason for about 95% of all IDispose Implementations - you may wrap around something that may need a Dispose.
using is just a shorthand for a: try, finally, NullCheck, Dispose. And finally runs in every possible case: it runs after a return. It runs on exception. It runs on GOTO's, continues and other jumps out it's block. It does not run on the OS killing the processe, but at that point it is kinda the OS/Finalizers responsibility anyway.
The best way of course would be not to return something disposeable from a function. Whatever data it has, just map it to something that does not use Disposeables. IIRC when working with SQLDataReader (wich requires a open connection), that is exactly what happens. You map the Query return value to any other collection that does not need a open connection.
If you can not do that, I would modify your code like this for peace of mind:
void Main()
{
using(var A= myMethod()){
//Anything you want to do with that variable
}
//using takes care of the Dispose call
}
Now anything can happen and I know using takes care of Disposing.

How can I do an action when a variable goes out of scope?

EDIT: So it looks like the only way to do this is with IDisposable. I suspected as much but it's still a bit of a bummer. I may make a class for this that takes an Action as #mjwills suggests but I still personally wish there was a way to do this without the using block. Alternative syntax like "using (var foo = new Bar([action]);" that makes the using statement apply to the block it's called from would be great.
In C# is it possible to perform an action when a variable goes out of scope? In C++ I would use an object's destructor to do something when it goes out of scope, but the garbage collector means I can't (cleanly) get the same behavior in C#. This is what I would write in C++:
class SetOnDestruction
{
bool& m_thingToSet;
bool m_newValueForThing;
public:
SetOnDestruction(bool& thingToSet, bool newValueForThing)
: m_thingToSet(thingToSet)
, m_newValueForThing(newValueForThing)
{
}
~SetOnDestruction()
{
m_thingToSet = m_newValueForThing;
}
};
void ExampleUsage()
{
bool thingToSet = true;
{
SetOnDestruction setter(thingToSet, false);
// do some stuff here
}
// thingToSet should now be false
}
I don't want to use IDisposable because then I'm wrapping my functions in big using blocks for what is really just a bit of syntactic sugar.
Does anyone know of anything relevant?
If you're trying to destroy unmanaged resources we can in fact use a destructor such as
~SetOnDestruction()
{
/* destruction things */
}
However, this gets called when the garbage collector destroys the object and thus is non-deterministic.
The only other way is using IDisposable
More info on IDisposable from MSDN here
Edit: In honor of the down votes (And pure interest) Let's see not if we should do this but if we can do this
We could hypothetically enforce local scope by calling something like this
class Program
{
static void Main(string[] args)
{
LocalScopeWrapper();
}
private static void LocalScopeWrapper() // maybe I could have a better name?
{
var testObj = new TestObj();
testObj.Print();
Console.WriteLine($"Total memory used before forced collect {GC.GetTotalMemory(false)}");
testObj = null;
GC.Collect(0); // Generation 0, lets only clear the smallest Small Object Heap
Console.WriteLine($"Total memory used after forced collect {GC.GetTotalMemory(true)}");
}
private class TestObj
{
public void Print()
{
Console.WriteLine("HelloWorld");
}
}
}
Here we're forcing the object to be collected after we set it to null. Makes sense, but not exactly what we want, and as Dire Whale asked for not clean.
But, I wanted to see if we emulate C++ behavior, and it is possible.
We could use Pinvoke and handles to pass our object to C/C++ libraries and call free as shown in this great answer by #xanatos
I was curious how bad we could get in C#, and this seemed like the ultimate of getting around the GC by letting a Pinvoke delete things under our nose. It isn't useful but interesting none the less.

Using 'Using' for things other than resource disposal [duplicate]

This question already has answers here:
Is it abusive to use IDisposable and "using" as a means for getting "scoped behavior" for exception safety?
(12 answers)
Closed 9 years ago.
We all know that the using statement is really good for resources you want to cleanup in a timely manner, such as an open file or database connection.
I was wondering if it would be considered a good thing to use the statement in cases where resources cleanup isn't the goal of the Dispose() method, but rather resetting to a previous state.
For example, a class that allows a using statement to wrap a procedure that takes a noticeable amount of time and changes the Cursor to a waiting state.
class CursorHelper : IDisposable
{
readonly Cursor _previousState;
public CursorHelper(Cursor newState)
{
_previousState = Cursor.Current;
Cursor.Current = newState;
}
public void Dispose()
{
Cursor.Current = _previousState;
}
}
Then the class can be used as such, without worrying about reverting the Cursor when your are done.
public void TimeIntensiveMethod()
{
using (CursorHelper ch = new CursorHelper(Cursors.WaitCursor))
{
// something that takes a long time to complete
}
}
Is this an appropriate use of the using statement?
There are certainly precedents for (ab)using the using statement in this way, for example FormExtensions.BeginForm in the ASP.NET MVC framework. This renders a <form> closing tag when it's disposed, and it's main purpose is to enable a more terse syntax in MVC views. The Dispose method attempts to render the closing tag even if an exception is thrown, which is slightly odd: if an exception is thrown while rendering a form, you probably don't want to attempt to render the end tag.
Another example is the (now deprecated) NDC.Push method in the log4net framework, which returns an IDisposable whose purpose is to pop the context.
Some purists would say it's an abuse, I suggest you form your own judgement on a case-by-case basis.
Personally I don't see anything wrong with your example for rendering an hourglass cursor.
The discussion linked in a comment by #I4V has some interesting opinions - including arguments against this type of "abuse" from the ubiquitous Jon Skeet.
In reality using is simply syntactical sugar for try/finally, so why don't you just do plain old try/finally like below...
try
{
// do some work
}
finally
{
// reset to some previous state
}
imho implementing the Dispose method to reset to some state would be very misleading, especially if you have consumers for your code.
I am opposed to this and believe it to be an abuse. I also think that RAII in C++ is a terrible idea. I am aware that I am in a minority on both positions.
This question is a duplicate. For detailed reasons on why I think this is an unwarranted abuse of the using statement, see: https://stackoverflow.com/a/2103158/88656
No, it isn't appropriate use of using and/or Dispose. The pattern has a very clear use ("Defines a method to release allocated resources."), and this isn't it. Any future developers using this code would look upon it with the contempt warranted for such evil.
If you want this kind of behaviour then implement events and expose them, calling code can subscribe to them and manage the cursor, if needs be, otherwise the cursor should be manageable by general parameters and maybe using Begin and End methods (although such naming conventions are generally reserved for asynchronous implementations of methods, you get the picture) - hacking this way doesn't actually buy you anything.
I my opinion it makes sense to use using-Disposable thing in a way other than just disposing objects. Of course it depends on the context and usage. If leads to a more readable code then it is ok.
I have had used it in a unit of work & repository pattern implementation like:
public class UnitOfWork: IDisposable {
// this is thread-safe in actual implementation
private static Stack<UnitOfWork> _uowStack = new Stack<UnitOfWork>();
public static UnitOfWork Current {get { return _uowStack.Peek(); }}
public UnitOfWork() {
_uowStack.Push(this);
}
public void Dispose() {
_ouwStack.Pop();
}
public void SaveChanges() {
// do some db operations
}
}
public class Repository {
public void DoSomething(Entity entity) {
// Do Some db operations
UnitOfWork.Current.SaveChanges();
}
}
With this implementation it is guaranteed that nested operations will use their corresponding UnitOfWork without passing parameter. Usage is like.
using (new UnitOfWork())
{
var repo1 = new UserRepository();
// Do some user operation
using (new UnitOfWork())
{
var repo2 = new AccountingRepository();
// do some accounting
}
var repo3 = new CrmRepository();
// do some crm operations
}
In this sample repo1 and repo3 use the same UnitOfWork while repo2 uses a different repository. What reader reads is "using new unit of work" and it makes a lot of sense.

Alternative syntax for C# using statement to automatically dispose objects?

I was wondering if anyone can think of a way to implement a mechanism that works like the using statement in C# but with a cleaner syntax.
In C++/CLR you can write
MyClass NewObject;
MyClass is a managed class here. As soon as the variable goes out of scope Dispose will be called. In essence, it does the same thing C# does with using but in a nicer way.
So, instead of writing
using (MyClass NewObject1=new MyClass())
{
xxxx;
using (MyClass NewObject2=new MyClass()
{
}
}
(I think this doesn't look very clean and it's also tedious to open a new block for every new variable)
I would prefer something like this:
autodispose MyClass NewObject1=new MyClass();
xxxx;
autodispose MyClass NewObject2=new MyClass();
Does anybody think it would be possible to implement something like this? It seems frameworks for AOP or code contracts use mechanisms that inject code but I am not sure how they do it.
MyClass is a managed class here. As soon as the variable goes out of scope Dispose will be called.
That's just not true, even in C++/CLR. My understanding is that C++/CLR still relies on the core .Net garbage collector for managed objects, rather than traditional C++ destructor semantics... and by those rules the object is disposed at some non-deterministic point in the future; it might be immediate... but more likely not. It will probably be fairly soon... but you can't be sure.
Even in the C# world, a using block is reserved for unmanaged resources (ie: anything other than RAM). You don't need to put just any object in a using block: most things can be safely created without one. When you need a using block is when there's something like a network connection, database connection, file handle, gdi resource, system timer, etc wrapped up in the type you're creating.
While I don't have answer I feel it's worth writing this up as an answer instead of just comments. The current answer with the most votes is as far as I know incorrect. According to Gordon Hogenson in Foundations of C++/CLI it does support "syntactic sugar or sleight of handle".... "To sum up, the heap-allocated object is immediately deleted at the end of the block, rather than lazily garbage collected, and as a consequence, the destructor is called immediately upon deletion." -emphasis mine, p 63 Stack vs. Heap Semantics
C++ programmers (pre smart pointers) are used to the fact that everything they new they must delete. However, when a C++ programmer creates a local variable, it does not have to be put on the heap. Stack semantics can be used and then the object doesn't have to explicitly deleted.
void Class::SomeMethod()
{
DbConnection connection; //No memory leak if not deleted
DbConnection leaky_connection = new DbConnection(); //on the heap will leak if not deleted
}
In C++/CLI it would look a little different for heap allocation:
DbConnection^ connection = gcnew DbConnection();
But since MS knew C++ programmers are used to stack semantics they allow the stack semantic version:
DbConnection connection;
And assuming the existence of :
~DbConnection()
{
//Close the connection
}
The stack semantic version will immediately call the destructor at the end of the method where connection is used.
I think the difficulty in doing this in C# is for the opposite of why it's allowed in C++/CLI (and here I may get into trouble). C# programmers are used to letting the garbage collector take care of things. They can allocate a local object stick it into a non-local container and not worry that it will go out of scope at the end of the method. The GC knows it's in the collection and it doesn't get prematurely destroyed. C# always deals with object references and you don't explicitly specify heap vs. stack storage. Implementing this "sleight of handle" in C# would probably break a lot of code and expectations.
In fact even the using statement syntax can create unexpected trouble in C#. I wrote up my favorite example of this in When Dispose Throws the Baby Out with the Bathwater a while back.
If you want to compact your using statements for typing brevity, why not do
using (MyClass class1 = new MyClass())
using (MyClass class2 = new MyClass())
using (MyClass class3 = new MyClass()) {
object xxxx;
// do some stuff
}
You can save your self some curly braces and a few extra lines since it seems that is what you're after, but its not significant. If you're brevity-OCD
using (var class1 = new MyClass())
using (var class2 = new MyClass())
using (var class3 = new MyClass()) {
object xxxx;
// do some stuff
}
By the way, using is a good thing for C#. You get to define the scope of the variable and you know exactly what the scope of that variable is, and when it will end. Where as otherwise, the scope could extend all the way into some other function even (eg. passing a reference to a function, or another object holding a reference to it).
This question is almost 9 years old, and there is now a better answer.
C# 8 introduced using declarations
A using declaration is a variable declaration preceded by the using keyword. It tells the compiler that the variable being declared should be disposed at the end of the enclosing scope.
As per the original question, instead of writing:
using (MyClass NewObject1=new MyClass())
{
// insert more code here;
using (MyClass NewObject2=new MyClass()
{
}
}
you can instead write:
using var newObject1 = new MyClass();
// insert more code here;
using var newObject2 = new MyClass();
The objects will be disposed when they go out of scope.

Enforcing an "end" call whenever there is a corresponding "start" call

Let's say I want to enforce a rule:
Everytime you call "StartJumping()" in your function, you must call "EndJumping()" before you return.
When a developer is writing their code, they may simply forget to call EndSomething - so I want to make it easy to remember.
I can think of only one way to do this: and it abuses the "using" keyword:
class Jumper : IDisposable {
public Jumper() { Jumper.StartJumping(); }
public void Dispose() { Jumper.EndJumping(); }
public static void StartJumping() {...}
public static void EndJumping() {...}
}
public bool SomeFunction() {
// do some stuff
// start jumping...
using(new Jumper()) {
// do more stuff
// while jumping
} // end jumping
}
Is there a better way to do this?
Essentially the problem is:
I have global state...
and I want to mutate that global state...
but I want to make sure that I mutate it back.
You have discovered that it hurts when you do that. My advice is rather than trying to find a way to make it hurt less, try to find a way to not do the painful thing in the first place.
I am well aware of how hard this is. When we added lambdas to C# in v3 we had a big problem. Consider the following:
void M(Func<int, int> f) { }
void M(Func<string, int> f) { }
...
M(x=>x.Length);
How on earth do we bind this successfully? Well, what we do is try both (x is int, or x is string) and see which, if any, gives us an error. The ones that don't give errors become candidates for overload resolution.
The error reporting engine in the compiler is global state. In C# 1 and 2 there had never been a situation where we had to say "bind this entire method body for the purposes of determining if it had any errors but don't report the errors". After all, in this program you do not want to get the error "int doesn't have a property called Length", you want it to discover that, make a note of it, and not report it.
So what I did was exactly what you did. Start suppressing error reporting, but don't forget to STOP suppressing error reporting.
It's terrible. What we really ought to do is redesign the compiler so that errors are output of the semantic analyzer, not global state of the compiler. However, it's hard to thread that through hundreds of thousands of lines of existing code that depends on that global state.
Anyway, something else to think about. Your "using" solution has the effect of stopping jumping when an exception is thrown. Is that the right thing to do? It might not be. After all, an unexpected, unhandled exception has been thrown. The entire system could be massively unstable. None of your internal state invariants might be actually invariant in this scenario.
Look at it this way: I mutated global state. I then got an unexpected, unhandled exception. I know, I think I'll mutate global state again! That'll help! Seems like a very, very bad idea.
Of course, it depends on what the mutation to global state is. If it is "start reporting errors to the user again" as it is in the compiler then the correct thing to do for an unhandled exception is to start reporting errors to the user again: after all, we're going to need to report the error that the compiler just had an unhandled exception!
If on the other hand the mutation to global state is "unlock the resource and allow it to be observed and used by untrustworthy code" then it is potentially a VERY BAD IDEA to automatically unlock it. That unexpected, unhandled exception might be evidence of an attack on your code, from an attacker who is dearly hoping that you are going to unlock access to global state now that it is in a vulnerable, inconsistent form.
I'm going to disagree with Eric: when to do this or not depends on the circumstances. At one point, I was reworking my a large code base to include acquire/release semantics around all accesses to a custom image class. Images were originally allocated in unmoving blocks of memory, but we now had the ability to put the images into blocks that were allowed to be moved if they hadn't been acquired. In my code, it is a serious bug for a block of memory to have slipped past unlocked.
Therefore, it is vital to enforce this. I created this class:
public class ResourceReleaser<T> : IDisposable
{
private Action<T> _action;
private bool _disposed;
private T _val;
public ResourceReleaser(T val, Action<T> action)
{
if (action == null)
throw new ArgumentNullException("action");
_action = action;
_val = val;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~ResourceReleaser()
{
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
_disposed = true;
_action(_val);
}
}
}
which allows me to do make this subclass:
public class PixelMemoryLocker : ResourceReleaser<PixelMemory>
{
public PixelMemoryLocker(PixelMemory mem)
: base(mem,
(pm =>
{
if (pm != null)
pm.Unlock();
}
))
{
if (mem != null)
mem.Lock();
}
public PixelMemoryLocker(AtalaImage image)
: this(image == null ? null : image.PixelMemory)
{
}
}
Which in turn lets me write this code:
using (var locker = new PixelMemoryLocker(image)) {
// .. pixel memory is now locked and ready to work with
}
This does the work I need and a quick search tells me I needed it in 186 places that I can guarantee won't ever fail to unlock. And I have to be able to make this guarantee - to do otherwise could freeze a huge chunk of memory in my client's heap. I can't do that.
However, in another case where I do work handling encryption of PDF documents, all strings and streams are encrypted in PDF dictionaries except when they're not. Really. There are a tiny number of edge cases wherein it is incorrect to encrypt or decrypt the dictionaries so while streaming out an object, I do this:
if (context.IsEncrypting)
{
crypt = context.Encryption;
if (!ShouldBeEncrypted(crypt))
{
context.SuspendEncryption();
suspendedEncryption = true;
}
}
// ... more code ...
if (suspendedEncryption)
{
context.ResumeEncryption();
}
so why did I choose this over the RAII approach? Well, any exception that happens in the ... more code ... means that you are dead in the water. There is no recovery. There can be no recovery. You have to start over from the very beginning and the context object needs to be reconstructed, so it's state is hosed anyway. And by comparison, I only had to do this code 4 times - the possibility for error is way, way less than in the memory locking code, and if I forget one in the future, the generated document is going to be broken immediately (fail fast).
So pick RAII when you absolutely positively HAVE to have the bracketed call and can't fail.
Don't bother with RAII if it is trivial to do otherwise.
If you need to control a scoped operation, I would add a method which take an Action<Jumper> to contain the required operations on the jumper instance:
public static void Jump(Action<Jumper> jumpAction)
{
StartJumping();
Jumper j = new Jumper();
jumpAction(j);
EndJumping();
}
An alternative approach that would work in some circumstances (i.e. when the actions can all happen at the end) would be to create a series of classes with a fluent interface and some final Execute() method.
var sequence = StartJumping().Then(some_other_method).Then(some_third_method);
// forgot to do EndJumping()
sequence.Execute();
Execute() can chain back down line and enforce any rules (or you can build the closing sequence as you build the opening sequence).
The one advantage this technique has over others is that you aren't limited by scoping rules. e.g. if you want to build the sequence based on user inputs or other asynchronous events you can do that.
Jeff,
what you're trying to achieve is generally referred to as Aspect Oriented Programming (AOP). Programming using AOP paradigms in C# is not easy - or reliable... yet. There are some capabilities built directly into the CLR and .NET framework that make AOP possible is certain narrow cases. For example, when you derive a class from ContextBoundObject you can use ContextAttribute to inject logic before/after method calls on the CBO instance. You can see examples of how this is done here.
Deriving a CBO class is annoying and restrictive - and there is another alternative. You can use a tool like PostSharp to apply AOP to any C# class. PostSharp is far more flexible than CBOs because it essentially rewrites your IL code in a postcompilation step. While this may seem a bit scary, it's very powerful because it allows you to weave in code in almost any way you can imagine. Here's a PostSharp example built on your use scenario:
using PostSharp.Aspects;
[Serializable]
public sealed class JumperAttribute : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionArgs args)
{
Jumper.StartJumping();
}
public override void OnExit(MethodExecutionArgs args)
{
Jumper.EndJumping();
}
}
class SomeClass
{
[Jumper()]
public bool SomeFunction() // StartJumping *magically* called...
{
// do some code...
} // EndJumping *magically* called...
}
PostSharp achieves the magic by rewriting the compiled IL code to include instructions to run the code that you've defined in the JumperAttribute class' OnEntry and OnExit methods.
Whether in your case PostSharp/AOP is a better alternative than "repurposing" the using statement is unclear to me. I tend to agree with #Eric Lippert that the using keyword obfuscates important semantics of your code and imposes side-effects and semantic menting to the } symbol at the end of a using block - which is unexpected. But is this any different than applying AOP attributes to your code? They also hide important semantics behind a declarative syntax ... but that's sort of the point of AOP.
One point where I whole-heartedly agree with Eric is that redesigning your code to avoid global state like this (when possible) is probably the best option. Not only does it avoid the problem of enforcing correct usage, but it can also help avoid multithreading challenges in the future - which global state is very susceptible to.
I don't actually see this as an abuse of using; I'm using this idiom in different contexts and never had problems... especially given that using is only a syntactic sugar. One way I use it to set a global flag in one of third party libraries I use, so that the change is reverted when finishing operations:
class WithLocale : IDisposable {
Locale old;
public WithLocale(Locale x) { old = ThirdParty.Locale; ThirdParty.Locale = x }
public void Dispose() { ThirdParty.Locale = old }
}
Note you don't need to assign a variable in using clause. This is enough:
using(new WithLocale("jp")) {
...
}
I slightly miss C++'s RAII idiom here, where the destructor is always called. using is the closest you can get in C#, I guess.
We have done almost exactly what you propose as a way to add method trace logging in our applications. Beats having to make 2 logging calls, one for entering and one for exiting.
Would having an abstract base class be helpful? A method in the base class could call StartJumping(), the implementation of the abstract method that child classes would implement, and then call EndJumping().
I like this style and frequently implement it when I want to guarantee some tear down behaviour: often it is much cleaner to read than a try-finally. I don't think you should bother with declaring and naming the reference j, but I do think you should avoid calling the EndJumping method twice, you should check if it's already been disposed. And with reference to your unmanaged code note: it's a finalizer that's typically implemented for that (although Dispose and SuppressFinalize are typically called to free up the resources sooner.)
I've commented on some of the answers here a bit about what IDisposable is and isn't, but I will reiterate the point that IDisposable is to enable deterministic cleanup, but does not guarantee deterministic cleanup. i.e. It's not guaranteed to be called, and only somewhat guaranteed when paired with a using block.
// despite being IDisposable, Dispose() isn't guaranteed.
Jumper j = new Jumper();
Now, I'm not going to comment on your use of using because Eric Lippert did a far better job of it.
If you do have an IDisposable class without requiring a finalizer, a pattern I've seen for detecting when people forget to call Dispose() is to add a finalizer that's conditionally compiled in DEBUG builds so that you can log something whenever your finalizer is called.
A realistic example is a class that's encapsulates writing to a file in some special way. Because MyWriter holds a reference to a FileStream which is also IDisposable, we should also implement IDisposable to be polite.
public sealed class MyWriter : IDisposable
{
private System.IO.FileStream _fileStream;
private bool _isDisposed;
public MyWriter(string path)
{
_fileStream = System.IO.File.Create(path);
}
#if DEBUG
~MyWriter() // Finalizer for DEBUG builds only
{
Dispose(false);
}
#endif
public void Close()
{
((IDisposable)this).Dispose();
}
private void Dispose(bool disposing)
{
if (disposing && !_isDisposed)
{
// called from IDisposable.Dispose()
if (_fileStream != null)
_fileStream.Dispose();
_isDisposed = true;
}
else
{
// called from finalizer in a DEBUG build.
// Log so a developer can fix.
Console.WriteLine("MyWriter failed to be disposed");
}
}
void IDisposable.Dispose()
{
Dispose(true);
#if DEBUG
GC.SuppressFinalize(this);
#endif
}
}
Ouch. That's quite complicated, but this is what people expect when they see IDisposable.
The class doesn't even do anything yet but open a file, but that's what you get with IDisposable, and the logging is extremely simplified.
public void WriteFoo(string comment)
{
if (_isDisposed)
throw new ObjectDisposedException("MyWriter");
// logic omitted
}
Finalizers are expensive, and the MyWriter above doesn't require a finalizer, so there's no point adding one outside of DEBUG builds.
With the using pattern I can just use a grep (?<!using.*)new\s+Jumper to find all places where there might be a problem.
With StartJumping I need to manually look at each call to find out if there is a possibility that an exception, return, break, continue, goto etc can cause EndJumping to not be called.
I dont think you want to make those methods static
You need to check in the dispose if end jumping has alredy been called.
If I call start jumping again what happens?
You could use a reference counter or a flag to keep track of the state of the 'jumping'. Some people would say IDisposable is only for unmanaged resources but I think this is ok. Otherwise you should make start and end jumping private and use a destructor to go with the constructor.
class Jumper
{
public Jumper() { Jumper.StartJumping(); }
public ~Jumper() { Jumper.EndJumping(); }
private void StartJumping() {...}
public void EndJumping() {...}
}

Categories