• YetAnotherReader (unregistered) in reply to YetAnotherReader
    nelle:
    can someone translate this in c++ with constructors and destructors ...

    second go... in the real world you would probably find that the Connector class is already in the libraries which came with the compiler...

    try { struct Connector { Connector(DB db) : _db(db) { _db.openConnection(); } ~Connector() { _db.closeConnection(); } private: DB _db; } connector(db); db.runSQL( sql ); } catch(SqlException sqlex) { error_panel.ErrorMessage = sqlex.Message; //.Procedure/.Line error_panel.Visible = true; }

  • CrankyPants (unregistered) in reply to Guran
    Guran:
    Hmm finally is indeed very useful....used right. [snip] File operations anyone? Database transactions?

    Exactly! The RWTF is that the author doesn't understand the use of finally blocks.

    Captcha: bathe (not today, thanks)

  • (cs) in reply to nelle
    nelle:
    finals can be usefull for something like this :

    Not exactly. Your open should be outside the try{} block that closes the connection, in its own try{}:

    try { db.openConnection(); try { db.runSQL( sql ); } catch(SqlException sqlex) { error_panel.ErrorMessage = sqlex.Message; //.Procedure/.Line error_panel.Visible = true; } finally { db.closeConnection(); } } // end of db.openConnection try catch(Exception ex) { // handle DB open failure, which is // probably not an SQL exception }

    I know, you probably just dashed something off as a quick example, but any example anywhere could end up copied into production code as a pattern.

  • (cs)

    Actually, in Delphi we can use two different blocks:

    try..finally..end
    which executes the block after finally regardless of whether an exception was raised or not, but does not trap the exception.
    try..except..end
    which executes the block after except only in the event of an exception, and traps it.

    They are usually nested as

    try
      // Constructor
      try
        // Code that does something and might fail
        // Commit, write, etcetera
      finally
        // Destructor, to be executed no matter what
      end;
    except
      on E: ExceptionType do
      begin
        // Do something with it, like rollback
      end;
    end;
    
  • (cs) in reply to brazzy
    brazzy:
    Steve:
    One more thing: no 'properly' written function should have multiple exit points - in theory, at least...
    IMO a very, very stupid theory that leads to horribly unmaintainable code in many cases.
    QFT. Martin Fowler makes much of how dumb the knobcheese "one entry, one exit" Old Skool dictum is throughout his Refactoring book. Without multiple exit points you have to nest if blocks that easily get overly complicated. Far simpler to have: if (test1) { return true; } if (test2) { return false; } if (test3) { return FILE_NOT_FOUND; } return NO_QUACK;

    than: var ret; if (test1) { ret = true; } else { if (test2) { ret = false; } else { if (test3) { ret = FILE_NOT_FOUND; } else { ret = NO_QUACK; } } } return ret;

    especially if you don't have elseif as a keyword in your language (and it's rendered superfluous by using exit points anyway)

  • Look at me! I'm on the internets! (unregistered) in reply to JonR
    JonR:
    i'm working with a codebase that is littered with

    try { // blah } catch(Exception e) { throw; }

    this makes me SO ANGRY

    What could possible be the point?

    I often do: try{ //something nasty }catch(SomeCheckedExceptionThatICantPossibleHandle ex) { throw new RuntimeException(ex); }

    A classic example is ThreadInterruptedException There's nothing I can do about it, and the only time I've ever seen one in the wild was in response to a System.exit() call. Might as well rethrow it as unchecked.

    The WTF here is why did java make some exceptions checked, when there is no way to recover from them.

  • Look at me! I'm on the internets! (unregistered) in reply to Look at me! I'm on the internets!
    Look at me! I'm on the internets!:
    A classic example is ThreadInterruptedException ...

    Should be InterruptedException, not ThreadInterruptedException

  • Dave (unregistered) in reply to mkb
    mkb:
    Actually Microsoft VC++ has a finally extension. Don't know if it's a preprocessor trick or a compiler extension.
    Structured Exception Handling. It's more of a C thing. Doesn't play well with C++.
  • Youssef (unregistered)

    It's very aparent that the guy was too lazy to lookup TryParse. It happens..

  • (cs) in reply to brazzy
    brazzy:
    Steve:
    One more thing: no 'properly' written function should have multiple exit points - in theory, at least...
    IMO a very, very stupid theory that leads to horribly unmaintainable code in many cases.

    I agree. A single exit point can sometimes lead to very bad code.

    I had a co-worker once who littered her code (Delphi) with all sorts of junk like this:

      strRet := 'Tina';
      if SomeValue = '1234' then
        strRet := 'ABCD';
      
      if strRet = 'Tina' then
        if SomeValue = '2345' then
          strRet := 'EFGH';
    
      // Snip another 200 tests like above.
    
      if strRet = 'Tina' then
        if SomeValue = '0987' then
          strRet := 'XYZA';
    
      Result := strRet;
    

    Code like that just stinks, and cries out for an earlier return to avoid the declaration of the test value and all the tests that have to be made.

  • Aaron (unregistered)

    Wow, gotta love some of these pearls of wisdom being posted in the comments...

    • People who catch Throwable or Error should have their hands cut off.

    Right, because it's actually physically possible to know every conceivable exception that a 3rd-party component might throw. And there's never a situation where you're, say, running a batch process with 15,000 subtasks, and you just want to log errors for individual errors rather than having the entire batch fail.

    Guys, there are valid reasons to catch generic exceptions. Now, it's rarely valid to catch and just ignore them, but if that's what you mean, then you have to qualify it that way.

    • No properly written function should have multiple exit points.

    Honestly, if this had any grounding in reality then don't you think the compilers would explicitly disallow it?

    A much better rule of thumb is that a function should return as early as possible. That leads to much better maintainability by humans and also minimzes the branch coverage needed by automated tests, if you're into that sort of thing.

  • Got enough wtfs of my own (unregistered)

    Actually the author is taking advantage of Java behavior. He is building a string. He doesn't want to bother with catching null pointers if something is null but a try forces SOMETHING like catch or finally. He uses multiple trys because he wants to build his string regardless if something in the middle dies.

    Although it is ugly and I wouldn't have coded it this way, it is efficient if in fact it is rare that one of them are null.

    Lighten up!

  • dkf (unregistered) in reply to Aaron
    Aaron:
    Wow, gotta love some of these pearls of wisdom being posted in the comments... - People who catch Throwable or Error should have their hands cut off. - No properly written function should have multiple exit points.
    Well someone has to supply some WTFs round here! (I've spent plenty of time in the past untangling the mess created by adherents of the above idiocies, and both are good ways of turning simple and robust code into horrible nightmares.)
  • G Money (unregistered)

    Remove all the try - finally blocks. The code works exactly the same.

  • dkf (unregistered) in reply to Alan
    Alan:
    I really think C++ should've had a finally {} before java/.NET did.
    This is wrong. Look up RAII (Resource Acquisition Is Initialization).
    That only works well if you can find some convenient (and relevant) scope to attach the lifetime of the object to. Often that's true, but not always. The relevance also matters, as it isn't good to force things to know about stuff they don't have to.
  • Belinski (unregistered) in reply to Alex
    Alex:
    Jon Skeet:
    Alex:
    I dont think the author of this piece knows much about programming in Java, still he seems to be quite happy to demonstrate his ignorance in public.

    Which piece of ignorance about Java? There's a typo where C++ should be C#, but the description of Java seems right to me. Admittedly there are finalizers, but they're not the same as C++ destructors as they're non-deterministic.

    What I would like to point out is that finally can be used for more than resource release - there are times when it would be very useful to have in C++, too...

    "finally" in Java is used not only to free local resources. In fact it is a proper way to free any kind of resources.

    finally is not just for freeing resources, but for doing anything that needs to be dealt with before the exception is thrown. They're not the same as C++ destructors for much more fundamental reasons than just determinism.

  • Reed Hedges (unregistered) in reply to aquanight
    aquanight:
    IMHO C++ does need a finally thanks to the new/delete operators.

    Foo *f = new Foo; try { f->bar(); } catch(std::exception& e) { delete f; throw; }

    What does the word "finally" even mean? It's a weird meaningless word. Catch means, very directly, when some exception is thrown in the try {} block, do this instead of continuing. Very simple.

  • John (unregistered)
    The reason C++ doesn't have this block is because it's unnecessary: since acquisition is initialization, most resources are local.

    The implication of that statement is that the only use of a finally block is to deallocate resource and, worse, that all deallocation should take place in a destructor! That's a pretty heavy restriction, considering the semantics of finally blocks are wide-open, i.e., the code in the finally block will be executed no matter what the return path is, and need not consist of "deallocation" routines or destructors.

  • MooseBrains (unregistered)

    I see that (anti) pattern quite a bit with our new guys here (in Java).

    private void doSomething() throws SomeException {
        try {
            doSomethingWhichThrows();
        }
        finally {
            cleanUp();
        }
    }

    My main gripe is really that it's not immediately obvious when you read it, but it does make perfect sense. Obviously if finally {} is empty it may as well be left out for readability sake. And the try {} if the method is declared to throw something.

    captcha: smile

  • Reed Hedges (unregistered) in reply to aquanight
    aquanight:
    You might wonder why one is allocating on the heap an object that might well only be used locally. The heap is generally several times larger than the stack, so there's nowhere better for obsenely large structures. Nevertheless, it's a pain the ass to remember a bunch of deletes before every exit point from the function.

    You can use the tools C++ provides to help you manage this. Namely, classes -- if you really must allocate obsenely large data structures of the heap, then it should be a class managing that data and representing it;

    class ObscenelyLargeData {
    private:
      int *data;
    public:
      ObscenelyLargeData(size_t datasize) {
       data = new int[datasize];
      }
      ~ObscenelyLargeData() {
        delete[] data;  
      }
      void calculate();
    };
    
    
    void function() {
      ObscenelyLargeData old(9999999999);
      try {
        old.compute();
      } catch(std::exception& e) {
        std::cerr << "oops!\n";
        return;
      }
    }
    
  • Reed Hedges (unregistered)
    aquanight:
    You might wonder why one is allocating on the heap an object that might well only be used locally. The heap is generally several times larger than the stack, so there's nowhere better for obsenely large structures. Nevertheless, it's a pain the ass to remember a bunch of deletes before every exit point from the function.

    You can use the tools C++ provides to help you manage this. Namely, classes -- if you really must allocate obsenely large data structures of the heap, then it should be a class managing that data and representing it;

    class ObscenelyLargeData {
    private:
      int *data;
    public:
      ObscenelyLargeData(size_t datasize) {
       data = new int[datasize];
      }
      ~ObscenelyLargeData() {
        delete[] data;  
      }
      void calculate();
    };
    
    
    void function() {
      ObscenelyLargeData old(9999999999);
      try {
        old.compute();
      } catch(std::exception& e) {
        std::cerr << "oops!\n";
        return;
      }
    }
    
  • anony coward (unregistered) in reply to chriseyre2000

    Seconded, everything you said.

    The 'rumor' here is that MS gave him a $1 million signing bonus, however.

    I've not been able to confirm it, but that was what was going around Borland during that time.

  • (cs)

    Some of you guys are obviously confusing two things. The Java and C# finally statement is NOT an equivalent to C++'s catch(...) statement. C++ provides a catch(...) statement that catches all exceptions regardless of their type because there is no forced single-rooted exception hierarchy. As I understand, catch(...) can be used to emulate finally:

    Java / C# code: try { acquireResource(); doSomethingRisky(); } finally { disposeResource(); }

    C++ code: try { acquireResource(); doSomethingRisky(); disposeResource(); } catch(...) { disposeResource(); throw; }

    C++ implementation produces duplicate code, but allows for greater flexibility. I wonder why Java doesn't support operator overloading "because it is too complicated", but supports exceptions. I think that operator overloading is easier to understand and use correctly. Granted, it has a greater abuse potential, like overloading a comma, but once people understand how to use this feature, they rarely come up with such bizarre ideas.

  • Mr. Nice Guy (unregistered) in reply to Steve
    Steve:
    One more thing: no 'properly' written function should have multiple exit points - in theory, at least...

    -- Steve

    And why not? I use this idiom all the time:

    // just a quick example... int open_file( char *st ) { if ( 0 == strcmp( st, "" ) ) { // no pathname provided - nothing to do... return( FILE_NAME_EMPTY_ERROR ); }

    // continue with processing... // comments don't throw exceptions... :-) return( SUCCESS ); }

    How else would you handle such a situation?

  • SomeCoder (unregistered) in reply to Look at me! I'm on the internets!
    Look at me! I'm on the internets!:
    JonR:
    i'm working with a codebase that is littered with

    try { // blah } catch(Exception e) { throw; }

    this makes me SO ANGRY

    What could possible be the point?

    I often do: try{ //something nasty }catch(SomeCheckedExceptionThatICantPossibleHandle ex) { throw new RuntimeException(ex); }

    A classic example is ThreadInterruptedException There's nothing I can do about it, and the only time I've ever seen one in the wild was in response to a System.exit() call. Might as well rethrow it as unchecked.

    The WTF here is why did java make some exceptions checked, when there is no way to recover from them.

    Also, what about this idiom: I'm inside a worker class that is doing some back end database stuff. Suddenly the database connection dies (or something equally catastrophic). There's not much else I can do at that point so the end user needs to know. I don't want the worker class putting up a dialog so rather than do that, I'll just re-throw the exception so the UI layer can catch it and deal with it (generally, display a message to the user).

    This is just one example and I suppose I could just get rid of the try/catch and let the exception propagate by itself but I prefer to have the >option< to perform some logging or to do something inside of the catch block rather than just let the exception fling itself up the stack by itself.

  • Simetrical (unregistered) in reply to dkf

    What would be an example where you couldn't create a useful scope?

    (do stuff not requiring foo)
    {
        Widget foo;
        (do everything you'll ever do with foo)
    }
    (proceed)
  • (cs)

    I've dealt with folks who don't do enough exception handling. Then there are those who take it to the other extreme, but don't quite get it. Sadly, I run into this a lot:

    try {
        // Stuff that might be Exceptional
    } catch (YourWtfCodeProjectileVomited ywcpv) {
      // ...
    } catch (YourWtfCodeMerelyChokedABit ywcmcab) {
      // ...
    } catch (RuntimeException re) {
      // ... you f'd up the JVM
    } catch (Exception e) {
      // ... you f'd up the OS
    } catch (Throwable t) {
      // Handle raw Errors: you are one whopping WTF!
    } finally {
      throw new IllegalStateException("WTF do I do now?");
    }

    And they'll throw a block like this around 3 lines of code, and again for the next 3, and so on, and then there's the Mother-of-All-Try-Catch-Finally (TM) blocks wrapped around the whole thing. Sheesh - look up refactor!

  • anonymous guy (unregistered)

    Everybody is wrong. The real WTF here is Java requiring extra cleanup code everywhere an object is used, rather than just once in the object itself (as C++ does). What a mess!!! heh.

    captcha cognac. Yes, please.

  • (cs) in reply to anonymous guy
    anonymous guy:
    Everybody is wrong. The real WTF here is Java requiring extra cleanup code everywhere an object is used, rather than just once in the object itself (as C++ does). What a mess!!! heh.

    captcha cognac. Yes, please.

    You might wish to read this

  • SpiritOfGrandeur (unregistered) in reply to Youssef
    Youssef:
    It's very aparent that the guy was too lazy to lookup TryParse. It happens..
    <rant> I hate the way that TryParse (in C#) always assumes you want the answer if it does Parse. I would like to 'int.TryParse(sInt)' instead of creating a variable that I will never use and doing 'int.TryParse(sInt, iInt)'. Overload the method please! </rant>
  • anonymous guy (unregistered) in reply to snoofle
    snoofle:
    anonymous guy:
    Everybody is wrong. The real WTF here is Java requiring extra cleanup code everywhere an object is used, rather than just once in the object itself (as C++ does). What a mess!!! heh.

    captcha cognac. Yes, please.

    You might wish to read this

    I do know about finalize(), although I will admit to not knowing Java as well as C++. But it's my understanding that it depends on the non-deterministic vagaries of the garbage collector. Which is not acceptable most of the time. Well, tell me I'm wrong, maybe I am...there are plenty of other things to hate about Java ;)

  • Hacky (unregistered) in reply to snoofle

    [quote user="snoofle"]

    try {
        // Stuff that might be Exceptional
    } catch (YourWtfCodeProjectileVomited ywcpv) {
      // ...
    } catch (YourWtfCodeMerelyChokedABit ywcmcab) {
      // ...
    } catch (RuntimeException re) {
      // ... you f'd up the JVM
    } catch (Exception e) {
      // ... you f'd up the OS
    } catch (Throwable t) {
      // Handle raw Errors: you are one whopping WTF!
    } finally {
      throw new IllegalStateException("WTF do I do now?");
    }

    Heh, this isn't that bad, because after all, you "gotta catch 'em all" :-P

  • waefafw (unregistered)

    Meh. Pretty small WTF. I've done the same thing a couple of times, just to remind myself that I need to add some finally code. Mind you, I actually get around to putting something in the finally block before I deploy. :)

  • (cs) in reply to snoofle
    snoofle:
    anonymous guy:
    Everybody is wrong. The real WTF here is Java requiring extra cleanup code everywhere an object is used, rather than just once in the object itself (as C++ does). What a mess!!! heh.

    captcha cognac. Yes, please.

    You might wish to read this

    You might wish to look into finalizers more. Not only are they not required to execute at a given point (the exit from a scope), they are not required to execute AT ALL if the GC never reclaims that object. (In other words, if the program exits before the GC is invoked, your finalizer won't be called.)

    In other words, they're next to useless.

  • (cs) in reply to Youssef
    Youssef:
    It's very aparent that the guy was too lazy to lookup TryParse. It happens..

    Until .NET 2.0, TryParse only existed on Double; you could "TryParse" ints with it, by providing an integer format indicator (too lazy to look it up ATM), and THEN, if successful, you could safely use Convert.ToInt32 or Int32.Parse to get the actual integer value, without doing error trapping.

    The coder's confusion with regards to TryParse is no mystery; that part of .NET 1.0 is the result of laziness and inconsistency in the designers. "We'll just put this method in Double, and people looking to parse integers should look there for it." In .NET and the tools, it's infrequently easier to hack around it than spend hours finding the real system facility for it.

  • Franz Kafka (unregistered) in reply to Bobby Knight
    Bobby Knight:
    My guess (which doesn't reduce the WTF-ness) is that they were coming from old VB and were fans of "ON ERROR NEXT". Exceptions confused them. They discovered (probably by accident) that using a try block, and then doing nothing with it, would keep the program trucking without "messing anything up"...recreating their beloved "ON ERROR NEXT"

    Well that makes sense in a way - people who habitually use ON ERROR NEXT are nincompetent in general, so why would C# make them any better.

  • YetAnotherReader (unregistered) in reply to anonymous guy
    anonymous guy:
    snoofle:
    anonymous guy:
    Everybody is wrong. The real WTF here is Java requiring extra cleanup code everywhere an object is used, rather than just once in the object itself (as C++ does). What a mess!!! heh.

    captcha cognac. Yes, please.

    You might wish to read this

    I do know about finalize(), although I will admit to not knowing Java as well as C++. But it's my understanding that it depends on the non-deterministic vagaries of the garbage collector. Which is not acceptable most of the time. Well, tell me I'm wrong, maybe I am...there are plenty of other things to hate about Java ;)

    I agree. The real WTF is thinking that a garbage collector (useful for freeing memory) could be a replacement for deterministic destructors (useful for freeing all resources).

    Main reason for introducing multiple destructors in MS C++/CLI. Another WTF...

  • Harry (unregistered) in reply to W
    W:
    aquanight:
    Catching Exception might be reasonable ("but you lose the exception type" - runtime type never goes away and if the exception was wrapped for rethrow (as it should be, to not f*k up the stack trace stored within) could be retrieved via instanceof, .getClass(), etc).
    If you don't like compile-time type checking, code in PHP. Catching Exception, then checking the runtime type? I've submitted code like that as a wtf before...

    I've used that as a tool to start a refactoring process when the original code caught exception and rethrew Exception, in other words replacing a WTF with a wtf.

  • Aaron (unregistered) in reply to Got enough wtfs of my own
    Got enough wtfs of my own:
    Actually the author is taking advantage of Java behavior. He is building a string. He doesn't want to bother with catching null pointers if something is null but a try forces SOMETHING like catch or finally. He uses multiple trys because he wants to build his string regardless if something in the middle dies.

    Although it is ugly and I wouldn't have coded it this way, it is efficient if in fact it is rare that one of them are null.

    How many times do people have to say "finally does not prevent the exception from propagating up the stack" before the other people will understand? Or maybe they just don't bother to read what's already been written on the subject (not a good attitude for a programmer to have).

    I could swear that the level of competence displayed in the comments here used to be higher than this. Now they're worse than the original "WTF" half of the time. Either that or they're posting the captcha (I'm sure the spammers appreciate that).

  • Dave C. (unregistered)

    So for those of you who are still confused, this:

    try
      {
          changes += Server.GetOrder(Convert.ToInt32(Status.Pending));
      }
      finally{}
    

    is exactly equivalent to this:

    changes += Server.GetOrder(Convert.ToInt32(Status.Pending));
    
  • (cs) in reply to Aaron
    Aaron:
    Got enough wtfs of my own:
    Actually the author is taking advantage of Java behavior. He is building a string. He doesn't want to bother with catching null pointers if something is null but a try forces SOMETHING like catch or finally. He uses multiple trys because he wants to build his string regardless if something in the middle dies.

    Although it is ugly and I wouldn't have coded it this way, it is efficient if in fact it is rare that one of them are null.

    How many times do people have to say "finally does not prevent the exception from propagating up the stack" before the other people will understand? Or maybe they just don't bother to read what's already been written on the subject (not a good attitude for a programmer to have).

    I could swear that the level of competence displayed in the comments here used to be higher than this. Now they're worse than the original "WTF" half of the time. Either that or they're posting the captcha (I'm sure the spammers appreciate that).

    int changes = 0;
    try {
      changes = Server.GetData(Convert.ToInt32(Status.Pending)).Results.Count;
    }
    finally {
      try {
        changes += Server.GetVersion(Convert.ToInt32(Status.Pending)).Count;
      }
      finally {
        try {
          changes += Server.GetOrder(Convert.ToInt32(Status.Pending));
        }
        finally {
          try {
            if (changes > 0) {
              StringOutput += StartFont( System.Drawing.Color.Red );
            }
          }
          finally {
            StringOutput += changes.ToString();
          }
        }
      }
    }
    

    :)

  • GrandmasterB (unregistered)

    It seems likely the guy was just inserting templates from his editor that included the 'finally'. Since the empty finally block doesnt actually do anything, this isnt much of a wtf.

  • ContractorInLivingHell (unregistered)

    Looks like auto-generated code or just plain newbie-misunderstanding code (ie, maybe he thought it was required as part of the syntax of try-catch when in fact it is not).

  • Alan (unregistered) in reply to Tweenk
    C++ code: try { acquireResource(); doSomethingRisky(); disposeResource(); } catch(...) { disposeResource(); throw; }

    C++ implementation produces duplicate code, but allows for greater flexibility.

    What you suggest is another anti-pattern. The idiomatic way to do it in C++ is:

    class Resource
    {
    public:
      Resource()
      {
        acquireResource() ;
      }
    
      ~Resource()
      {
        releaseResource() ;
      }
    };
    

    Then to use the resource:

    void somefunction()
    {
      // No try/catch blocks at all!
      Resource r ;
      doSomethingRisky() ;
    }
    
  • steven22 (unregistered)

    hey, most (of other people's) code that I read doesn't even have the try part. So he gets some points for at least trying a little bit.

  • Artemus Harper (unregistered)

    I commonly use try--finally blocks to undo a tempory change. E.g. This is a "recursion" safe version ToString for a Collection.

    [ThreadLocal] private bool inToString = false; public override string ToString() { if(inToString) return "..."; else { inToString = true; try { StringBuilder ret = new StringBuilder("{"); foreach(T obj in this) { ret.Append(String.valueOf(obj)); //whatever the c# function is. ret.Append(","); } ret.Append("}"); } finally { inToString = false; } } }

    I also commonly use it when disabling gui buttons while doing an operation, and re-enabling them in a finally block.

    Using a constructor and destructor to do more than the initialization of the object is an anti-pattern.

  • noname (unregistered) in reply to dkf
    dkf:
    Alan:
    I really think C++ should've had a finally {} before java/.NET did.
    This is wrong. Look up RAII (Resource Acquisition Is Initialization).
    That only works well if you can find some convenient (and relevant) scope to attach the lifetime of the object to. Often that's true, but not always. The relevance also matters, as it isn't good to force things to know about stuff they don't have to.

    Are you really that dumb???

    If you don't have a convenient scope, where the heck are you going to place your finally???

    And are you arguing for or against C++ with that last comment? Why should so many random finally blocks need to know the (easy to forget) cleanup details when the objects themselves can handle it?

  • (cs) in reply to KenW
    KenW:
    I had a co-worker once who littered her code (Delphi) with all sorts of junk like this:

    if I remember correctly Delphi (I have not done Delphi for more than a year, and I would confirm it, but I would have to reinstall it on my computer) doesn't have a return statement, the only thing that is close to a return statement is:

    Result := <return value>; exit;

    OR

    FunctionName := <return value>; exit;

  • noname (unregistered) in reply to Artemus Harper
    Artemus Harper:
    I commonly use try--finally blocks to undo a tempory change. E.g. This is a "recursion" safe version ToString for a Collection.

    [ThreadLocal] private bool inToString = false; public override string ToString() { if(inToString) return "..."; else { inToString = true; try { StringBuilder ret = new StringBuilder("{"); foreach(T obj in this) { ret.Append(String.valueOf(obj)); //whatever the c# function is. ret.Append(","); } ret.Append("}"); } finally { inToString = false; } } }

    I also commonly use it when disabling gui buttons while doing an operation, and re-enabling them in a finally block.

    Using a constructor and destructor to do more than the initialization of the object is an anti-pattern.

    I suppose you could solve that problem over and over again when you need to. Or, you could solve it once.

    class nest; class nest_var { friend nest;

    public: bool is_nested() { return depth != 0; }

    int get_depth() { return depth; }

    private: int depth = 0; }

    class nest { public: nest(nest_var &_var) : var(_var) { var.depth++; }

    ~nest() { var.depth--; }

    private: nest_var &var; }

    ................

    class some_class { private: nest_var guard;

    .........

    void some_func() { if (guard.is_nested()) { //Do something } else { nest(guard);

         //Do something else
      }
    

    } .........

    }

    I used something very similar to handle calls to UpdateData in an MFC application. I also found other users for it throughout the code base.

    The best part is if it's ever needed I can change out the implementation of nest & nest_var to transparently deal with multithreading.

  • noname (unregistered) in reply to Artemus Harper

    Using a constructor and destructor to do more than the initialization of the object is an anti-pattern.

    I'm afraid it's not that simple.

    The purpose of a constructor is to prepare the environment so the object can safely do it's work.

    The purpose of a destructor is to reset the environment back to the state it was in before the constructor was called (except for documented intentional side effects).

    In an ideal world "the environment" is limited to the local members of the class, and it devolves into your example. But, if the real world was always that simple we'd all be using Haskell.

Leave a comment on “Nothing Final”

Log In or post as a guest

Replying to comment #:

« Return to Article