Author Topic: On Error Return Nothing  (Read 4367 times)

0 Members and 1 Guest are viewing this topic.

Peter Jamtgaard

  • Guest
On Error Return Nothing
« on: January 22, 2013, 03:50:33 PM »
I am playing with some code that ... I would like to create a function "On Error Return Nothing" function to add to my code so I can convert this try catch stuff as shown below... I want my functions to return nothing if they fail.

Code: [Select]
Public Shared ReadOnly Property TestFunction(ByVal strValue As String)
        Get
            Try
                  Return ... "Do Something with strValue"

            Catch ex As Exception

            End Try
            Return Nothing
        End Get
    End Property

What I would like instead is:

Code: [Select]

    Public Shared ReadOnly Property TestFunction(ByVal strValue As String)
        Get
            On Error Return Nothing
            Return ... "Do Something with strValue"
        End Get
    End Property

n.yuan

  • Bull Frog
  • Posts: 348
Re: On Error Return Nothing
« Reply #1 on: January 22, 2013, 04:15:16 PM »
I am playing with some code that ... I would like to create a function "On Error Return Nothing" function to add to my code so I can convert this try catch stuff as shown below... I want my functions to return nothing if they fail.

Code: [Select]
Public Shared ReadOnly Property TestFunction(ByVal strValue As String)
        Get
            Try
                  Return ... "Do Something with strValue"

            Catch ex As Exception

            End Try
            Return Nothing
        End Get
    End Property


You simply place Return Nothing between "Catch" And "End Try", where is what the "Catch" is meant for.

I'd never want to go back the old VB stype of "On Error GoTo/Resume......"

Peter Jamtgaard

  • Guest
Re: On Error Return Nothing
« Reply #2 on: January 22, 2013, 05:17:09 PM »
I am aware that I can do it with a try/catch/finally expression...

What I want to do is clean up my code so I don't have to have a bazillion try catch expressions in my code.

I want to create the code for the "On Error Return Nothing" expression to fundamentally do what the try/catch expression is doing in one line instead of 4 lines.

I was playing around with predicate and action functions to see if I could pass an expression to another function and trap the errors.

Thoughts.

Here is a version where it is 2 lines versus 4 with the try/catch

Code: [Select]
   Public Shared ReadOnly Property TestFunction(ByVal strValue As String)
        Get
            On Error Goto Error1
            Return ... "Do Something with strValue"
Error1:     Return Nothing
        End Get
    End Property
« Last Edit: January 22, 2013, 08:53:21 PM by peterj »

Jeff H

  • Needs a day job
  • Posts: 6150
Re: On Error Return Nothing
« Reply #3 on: January 23, 2013, 01:29:41 PM »

Not quite sure I understand the question or intent, but there is a wealth of information out there that covers this in detail,
but wouldn't you have to use error handling to avoid using error handling?


For starters "Nothing" is evaluated differently for reference types and value types.


For a value type it returns the default value so integer = 0, boolean = false, etc..... 
For a reference type it means it does not point to any instance of an object.


So for a method to return Nothing will vary by type.


When a exception happens the runtime will start walking back up the call stack to pass execution to code that handles it.


There is no function that I know of that will replace a try catch block unless I guess you create some generic functions like Action & Func that swallow the errors and you pass all your other functions through them.


It would probably be best to update error handling in code, because for example if accessing a file seems like you would want to handle appropriate IOexception


Also I do not think you can have Labels(GoTo) inside properties.




Let me take a moment of silence to ask the code Gods to forgive me for what I am about to post.
I am sorry if this offends anyone and it hurts me more to post this than for you to read it.
Code - Visual Basic: [Select]
  1.  
  2.     Sub Main()
  3.         Dim o As Object = Nothing
  4.         Console.WriteLine(pooFunction(o))
  5.         Console.Read()
  6.  
  7.  
  8.     End Sub
  9.     Public Function pooFunction(ByVal val As Object) As Object
  10.         On Error GoTo ErrorHandler
  11.         Return val.ToString & " This is bad"
  12.  
  13.  
  14. ErrorHandler:
  15.  
  16.  
  17.         Resume Next
  18.     End Function
  19.  
« Last Edit: January 23, 2013, 01:38:02 PM by Jeff H »

BlackBox

  • King Gator
  • Posts: 3770
Re: On Error Return Nothing
« Reply #4 on: January 23, 2013, 03:14:27 PM »
Let me take a moment of silence to ask the code Gods to forgive me for what I am about to post.
I am sorry if this offends anyone and it hurts me more to post this than for you to read it.
Code - Visual Basic: [Select]
  1.  
  2.     Sub Main()
  3.         Dim o As Object = Nothing
  4.         Console.WriteLine(pooFunction(o))
  5.         Console.Read()
  6.  
  7.  
  8.     End Sub
  9.     Public Function pooFunction(ByVal val As Object) As Object
  10.         On Error GoTo ErrorHandler
  11.         Return val.ToString & " This is bad"
  12.  
  13.  
  14. ErrorHandler:
  15.  
  16.  
  17.         Resume Next
  18.     End Function
  19.  

 :-D
"How we think determines what we do, and what we do determines what we get."

dgorsman

  • Water Moccasin
  • Posts: 2437
Re: On Error Return Nothing
« Reply #5 on: January 23, 2013, 05:58:20 PM »
Agreed.  Should be the standard foo-style naming for That Which Is Bad Practice examples.
If you are going to fly by the seat of your pants, expect friction burns.

try {GreatPower;}
   catch (notResponsible)
      {NextTime(PlanAhead);}
   finally
      {MasterBasics;}

Peter Jamtgaard

  • Guest
Re: On Error Return Nothing
« Reply #6 on: January 25, 2013, 01:22:26 PM »
I found the on error goto OnError syntax and have been using it.

I prefer to have my functions return nothing if they fail that way I can drop out of the loop or whatever.

If X IsNot Nothing then

is a good test.

I am open to another convention that would do the same thing.

Suggestions for a value that can be returned by all variable types that can be tested?

Also good structured programming IMHO should segregate the activities into functions (instead of long run on spaghetti code), and each function should handle its own errors.

P=
« Last Edit: January 25, 2013, 01:46:55 PM by peterj »

kaefer

  • Guest
Re: On Error Return Nothing
« Reply #7 on: January 25, 2013, 02:07:54 PM »
Suggestions for a value that can be returned by all variable types that can be tested?

Restrict yourself to reference types.
Use System.Nullable.
Look at Haskell's Maybe monad or, closer to home, the FSharp option type.

Also good structured programming IMHO should segregate the activities into functions (instead of long run on spaghetti code), and each function should handle its own errors.

Also good property getters should be IMicrosoft'sHO simple operations without any preconditions. If a getter might throw an exception, consider redesigning the property to be a method. By extension, this precludes the getter from returning Nothing if it would otherwise throw an exception.

Peter Jamtgaard

  • Guest
Re: On Error Return Nothing
« Reply #8 on: January 25, 2013, 07:03:35 PM »
I can think of quite a few times when Microsoft's HO has been problematic.

It is like putting the fox in charge of the hen house.

P=







« Last Edit: January 25, 2013, 07:39:38 PM by peterj »

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: On Error Return Nothing
« Reply #9 on: January 25, 2013, 07:21:35 PM »

Peter,
Without knowing the full extent of what you are trying to do :
It seems to me that you may me mixing up the concepts of exceptions and assertion testing.

I want an exception thrown if I have an error in logic or a failure in data.

I want to be advised and offered options if some of my expectations/assertions are not met.

As a user, I wouldn't want unexpected changes to my locked layers or object properties.

Having a layer locked is not an error ... it is a precondition that may need to be tested and handled as such.


kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

Peter Jamtgaard

  • Guest
Re: On Error Return Nothing
« Reply #10 on: January 25, 2013, 07:42:46 PM »
As I said, because .net can cause a fatal error in AutoCAD so easily...

I just like to know if any function or sub fails, but I want the error to be trapped at the level of the function, and I want the program to continue to run.

I wish I had a better example to share...

When I come across one I will post it.

p=

TheMaster

  • Guest
Re: On Error Return Nothing
« Reply #11 on: January 27, 2013, 02:31:38 AM »
Suggestions for a value that can be returned by all variable types that can be tested?

Restrict yourself to reference types.
Use System.Nullable.
Look at Haskell's Maybe monad or, closer to home, the FSharp option type.


There are no reference types in LISP and the only reference types a LispFunction can return back to LISP are strings and selection sets, either of which would be translated to NIL. Everything else is a value type (namely ints, doubles, ObjectIds).

A LispFunction can return NIL back to LISP, but I don't see what good that would do, since NIL (an empty list) could be a legitimate result, which of course, means that it can't be used to signal a failure.

While trapping exceptions to prevent AutoCAD from failng is in most cases, necessary, allowing calling code to continue to run as if the error didn't happen, is IMO, illegitimate.


huiz

  • Swamp Rat
  • Posts: 919
  • Certified Prof C3D
Re: On Error Return Nothing
« Reply #12 on: January 27, 2013, 03:17:30 AM »
As I said, because .net can cause a fatal error in AutoCAD so easily...

I just like to know if any function or sub fails, but I want the error to be trapped at the level of the function, and I want the program to continue to run.

I wish I had a better example to share...

When I come across one I will post it.

p=

If you catch the exception as a system.exception (i.e. "Catch ex as System.Exception") then you can catch the error nicely so you are able to write code to nicely stop your application. But if you only catch the error as Exception (which is probably an Autodesk.AutoCAD.Runtime.Exception), then you get a Fatal Error as result.

More info about this: http://www.theswamp.org/index.php?topic=41034.msg462424#msg462424

The conclusion is justified that the initialization of the development of critical subsystem optimizes the probability of success to the development of the technical behavior over a given period.

TheMaster

  • Guest
Re: On Error Return Nothing
« Reply #13 on: January 27, 2013, 05:49:06 AM »
As I said, because .net can cause a fatal error in AutoCAD so easily...

That's not a legitimate reason to allow a program to continue to run after an unexpected error.

It is true that you must trap exceptions to prevent AutoCAD from failing (usually because of a hardware exception like a NullReferenceException, which for some strange reason, AutoCAD's managed runtime will not catch when it is thrown from an invoked LispFunction or CommandMethod).

But where are you mistaken is, the idea that in the case of an exception, you should return a value indicating failure, and allow the calling LISP code to continue to run.

What I do is trap all exceptions, and if one is raised, I then throw another exception that is translated into a LISP error condition that can be caught using vl-catch-all-apply, or by an *error* function.

Allowing the calling LISP code to continue to run is breaking one of the most basic rules of programming. If a program is allowed to continue to run after an unexpected error, it can corrupt the user's data without you or them ever knowing it happened.

That is why bugs that cause a program to fail are far preferable to bugs that don't cause a failure, but rather only corrupt the user's data.

To help make the reasons why exceptions must be caught in LispFunctions and CommandMethods clearer, and to see a few ways of simplifying what you must do to ensure AutoCAD doesn't crash, see the included sample code.

Code - C#: [Select]
  1.  
  2. /// Kaboom.cs  Copyright (c) Tony Tanzillo 2013.
  3. ///
  4. /// The following code contains implementations of
  5. /// three externally-defined LISP functions:
  6. ///
  7. ///    (safe-kaboom)
  8. ///    (unsafe-kaboom)
  9. ///    (ez-safe-kaboom)
  10. ///    
  11. /// All functions take one or more arguments.
  12. ///
  13. /// If you pass any of them two arguments and both
  14. /// arguments are NIL, like so:
  15. ///
  16. ///    Command: (unsafe-kaboom nil nil)
  17. ///    
  18. /// A bug in the TypedValue's == operator triggers
  19. /// a NullReferenceException.
  20. ///
  21. /// The (unsafe-kaboom) function provides no safety-net,
  22. /// and doesn't catch any exceptions thrown by the call
  23. /// to the KaboomHelper() method, and as a result, the
  24. /// call '(unsafe-kaboom nil nil)' will crash AutoCAD.
  25. ///
  26. /// Some mistakenly believe that AutoCAD will catch any
  27. /// exception that's raised in code called in or from
  28. /// a LispFunction or CommandMethod handler, and make
  29. /// the mistake of relying on AutoCAD's managed runtime
  30. /// to act as the safety-net that prevents managed code
  31. /// from doing serious damage, such as crashing AutoCAD
  32. /// which often results in the loss of unsaved work.
  33. ///
  34. /// That is simply not the case.
  35. ///
  36. /// AutoCAD's managed runtime does catch most exceptions
  37. /// raised by the CLR, but does not catch all exceptions,
  38. /// including NullReferenceExceptions that are signaled
  39. /// in hardware, rather than by the CLR. If you do not
  40. /// implement an exception handler within a LispFunction
  41. /// or CommandMethod handler, there's an excellent chance
  42. /// that AutoCAD will crash if your code contains a bug
  43. /// that triggers a NullReferenceException, or other low-
  44. /// level or hardware-signaled exception.
  45. ///
  46. /// The handler for the (safe-kaboom) LISP function shows
  47. /// how you must deal with exceptions that can be thrown
  48. /// from code in LispFunctions and CommandMethods (or any
  49. /// code called from those contexts).
  50. ///
  51. /// (safe-kaboom) traps any exception, including those
  52. /// that AutoCAD's managed runtime fail to catch, and
  53. /// simply rethrows them as managed exceptions.
  54. ///
  55. /// Re-throwing an exception from managed code is what
  56. /// allows AutoCAD's runtime to catch the exception and
  57. /// prevents it from becoming fatal.
  58. ///
  59. /// The call '(safe-kaboom nil nil)', also results in a
  60. /// NullReferenceException, but because that exception
  61. /// is caught by the SafeKaboom() LispFunction handler,
  62. /// and re-thrown as a managed exception, the AutoCAD
  63. /// managed runtime will catch it, and AutoCAD will not
  64. /// go belly-up.
  65. ///
  66. /// The handler for the (ez-safe-kaboom) LISP function
  67. /// shows a more-advanced, structured way to deal with
  68. /// the problem, using delegates and lambda functions.
  69. ///
  70.  
  71. using System;
  72. using System.Collections.Generic;
  73. using System.Linq;
  74. using System.Text;
  75. using Autodesk.AutoCAD.Runtime;
  76. using Autodesk.AutoCAD.DatabaseServices;
  77.  
  78. namespace KaboomSample
  79. {
  80.    public static class Kaboom
  81.    {
  82.  
  83.       /// <summary>
  84.       /// Calling this with two nils as
  85.       /// show below, will crash AutoCAD:
  86.       ///
  87.       ///    Command: (unsafe-kaboom nil nil)
  88.       ///    
  89.       /// </summary>
  90.  
  91.       [LispFunction( "UNSAFE-KABOOM" )]
  92.       public static bool UnsafeKaboom( ResultBuffer args )
  93.       {
  94.          return KaboomHelper( args );
  95.       }
  96.  
  97.       /// <summary>
  98.       /// Calling this with the same arguments
  99.       /// shown above, will result in an error
  100.       /// condition, without crashing AutoCAD.
  101.       /// </summary>
  102.  
  103.       [LispFunction( "SAFE-KABOOM" )]
  104.       public static bool SafeKaboom( ResultBuffer args )
  105.       {
  106.          /// The try/catch blocks catch exceptions
  107.          /// that may not be caught by AutoCAD, and
  108.          /// will most-likely become fatal:
  109.          try
  110.          {
  111.             return KaboomHelper( args );
  112.          }
  113.          catch( System.Exception ex )    /// <- variable is required !
  114.          {
  115.             /// The exception that was thrown may be a
  116.             /// hardware-signaled or SEH exception, in
  117.             /// which case AutoCAD's managed runtime may
  118.             /// not be able to catch it, resulting in it
  119.             /// becoming fatal.
  120.             ///
  121.             /// The way to prevent that from happening
  122.             /// is to simply re-throw the exception as
  123.             /// a managed exception, allowing AutoCAD's
  124.             /// managed runtime to catch it. Note that
  125.             /// we declare the exception variable in the
  126.             /// catch() statement because if we don't do
  127.             /// that, the effect is the same as having
  128.             /// no catch block at all.
  129.             ///
  130.             /// In other words, do NOT do this:
  131.             ///
  132.             ///    try
  133.             ///    {
  134.             ///       /// some code that may fail
  135.             ///    }
  136.             ///    catch      
  137.             ///    {
  138.             ///       throw;
  139.             ///    }
  140.             ///    
  141.             /// What you see above may NOT allow AutoCAD to
  142.             /// catch the re-thrown exception. That may be
  143.             /// because the compiler may simply discard the
  144.             /// catch block entirely as it does nothing, or
  145.             /// behave as if the catch block doesn't exist.
  146.             ///
  147.             /// So, you must declare an exception variable,
  148.             /// and throw that variable, as shown in the
  149.             /// code examples.
  150.             ///
  151.             /// Of course, it should go without saying,
  152.             /// that you may want to do something else
  153.             /// when an exception is caught, depending
  154.             /// on the type of the exception and/or the
  155.             /// specifics of your application.
  156.  
  157.             throw ex;
  158.          }
  159.       }
  160.  
  161.       /// <summary>
  162.       ///
  163.       /// Works like SafeKaboom(), except that it
  164.       /// uses a helper method that does the work
  165.       /// of catching and re-throwing exceptions,
  166.       /// making it possible for them to be caught
  167.       /// by AutoCAD's managed runtime:
  168.       ///
  169.       /// </summary>
  170.  
  171.       [LispFunction( "EZ-SAFE-KABOOM" )]
  172.       public static bool EZSafeKaboom( ResultBuffer args )
  173.       {
  174.          return SafeInvoke( KaboomHelper, args );
  175.       }
  176.  
  177.       /// <summary>
  178.       ///
  179.       /// By-design, this method will throw a
  180.       /// NullReferenceException when passed
  181.       /// a ResultBuffer containing exactly
  182.       /// two RTNIL's .
  183.       ///
  184.       /// The exception results from a bug in
  185.       /// the TypedValue's == operator, that
  186.       /// mistakenly uses Object.Equals (the
  187.       /// instance version) on left operand's
  188.       /// Value property, without fist doing
  189.       /// a null check on it.
  190.       ///
  191.       /// </summary>
  192.  
  193.       static bool KaboomHelper( ResultBuffer args )
  194.       {
  195.          if( args == null )
  196.             return false;
  197.          TypedValue[] array = args.AsArray();
  198.          if( array.Length != 2 )
  199.             return false;
  200.          TypedValue a = array[0];
  201.          TypedValue b = array[1];
  202.          return a == b;
  203.       }
  204.  
  205.       /// <summary>
  206.       /// Helper methods that will invoke a passed
  207.       /// delegate inside a try block, and catch any
  208.       /// exception thrown, including ones that are
  209.       /// not catchable by AutoCAD's managed runtime,
  210.       /// and re-throw the exception, allowing it to
  211.       /// be caught by the AutoCAD runtime.
  212.       ///
  213.       /// Why all this bullshit is necessary,
  214.       /// is the $60,000 question.
  215.       ///
  216.       /// </summary>
  217.       /// <param name="action"></param>
  218.  
  219.       public static void SafeInvoke( Action action )
  220.       {
  221.          try
  222.          {
  223.             action();
  224.          }
  225.          catch( System.Exception ex )
  226.          {
  227.             /// Here you can also do other things,
  228.             /// like log the exception, generate a
  229.             /// CER (customer error report), send
  230.             /// an email, SMS, tweet 8), etc...
  231.             ///
  232.             /// But you still have to re-throw here,
  233.             /// or the calling LISP code will never
  234.             /// know what happened.
  235.  
  236.             throw ex;
  237.          }
  238.       }
  239.  
  240.       /// Same as above, but returns a value
  241.  
  242.       public static T SafeInvoke<T>( Func<T> func )
  243.       {
  244.          try
  245.          {
  246.             return func();
  247.          }
  248.          catch( System.Exception ex )
  249.          {
  250.             throw ex;
  251.          }
  252.       }
  253.  
  254.       /// Same as a above, but also takes an argument
  255.       /// and returns a value.
  256.      
  257.       public static T SafeInvoke<TArg, T>( Func<TArg, T> func, TArg arg )
  258.       {
  259.          try
  260.          {
  261.             return func( arg );
  262.          }
  263.          catch( System.Exception ex )
  264.          {
  265.             throw ex;
  266.          }
  267.       }
  268.  
  269.    }
  270. }
  271.  
  272.  

Output:

Code - Text: [Select]
  1.  
  2. Command: (safe-kaboom nil nil)
  3.  
  4. System.NullReferenceException: Object reference not set to an instance of an
  5. object.
  6.    at KaboomSample.Kaboom.SafeKaboom(ResultBuffer args) in
  7. D:\VS08\Misc\Linq2Lisp\ExtensionLoaderTest\Kaboom.cs:line 138
  8.    at Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorker(MethodInfo mi, Object
  9. commandObject, Boolean bLispFunction)
  10.    at
  11. Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorkerWithExceptionFilter(MethodInfo
  12.  mi, Object commandObject, Boolean bLispFunction)
  13.    at Autodesk.AutoCAD.Runtime.CommandClass.CommandThunk.InvokeLisp(); error:
  14. ADS request error
  15.  
  16. Command: (ez-safe-kaboom nil nil)
  17.  
  18. System.NullReferenceException: Object reference not set to an instance of an
  19. object.
  20.    at KaboomSample.Kaboom.SafeInvoke[TArg,T](Func`2 func, TArg arg) in
  21. D:\VS08\Misc\Linq2Lisp\ExtensionLoaderTest\Kaboom.cs:line 246
  22.    at Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorker(MethodInfo mi, Object
  23. commandObject, Boolean bLispFunction)
  24.    at
  25. Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorkerWithExceptionFilter(MethodInfo
  26.  mi, Object commandObject, Boolean bLispFunction)
  27.    at Autodesk.AutoCAD.Runtime.CommandClass.CommandThunk.InvokeLisp(); error:
  28. ADS request error
  29.  
  30. Command: (unsafe-kaboom nil nil)
  31.  
  32.    (AutoCAD Terminates)
  33.  
  34.  
« Last Edit: January 27, 2013, 10:27:27 AM by TT »