C # either returns false or does nothing

I am wondering if there is a way not to repeat the same construct , but rather call StatusCheck () . He cannot return true when he succeeds. Does anyone know a better name for this question?

bool Enable() { if (!GetStatus(ref status)) { Trace.WriteLine("Error"); return false; } // do stuff if (!GetStatus(ref status)) { Trace.WriteLine("Error"); return false; } // do more stuff if (!GetStatus(ref status)) { Trace.WriteLine("Error"); return false; } // do even more stuff // 6 more times the above return true; } 
+3
source share
11 answers

You can create a CheckStatus() method that throws an exception if the status is invalid, then handle this exception in the Enable() method:

 public void CheckStatus(int status) { if (!IsValidStatus(status)) { throw new InvalidStatusException(status); } } public bool Enable() { try { CheckStatus(status); // do stuff CheckStatus(status); // do more stuff CheckStatus(status); // do even more stuff // 6 more times the above return true; } catch (InvalidStatusException) { Trace.WriteLine("Error"); return false; } } 
+6
source

I would get the code represented by the "Do things" comments reorganized into methods. You call these methods and either throw exceptions or check the return value of these methods (which may be the current status), rather than repeatedly calling GetStatus() .

Also, I don’t understand why the method named GetStatus() will have a ref parameter, which, apparently, will be updated by the method with the current status? If you must have the GetStatus() method, I would have GetStatus() not accept arguments and actually return the current status.

those.

 Status status = GetStatus(); 

If you decide to allow these methods to throw exceptions, be careful that you do not begin to apply real logic when throwing these exceptions - exceptions are not the right way to control the flow of programs .

+6
source

Depending on how serious you want to be, you could create some sort of sequence of actions so that he develops a “do-stuff” in the methods.

 protected delegate void DoStuffDelegate(ref {TYPE} statusToCheck); bool Enable() { List<DoStuffDelegate> stuffToDo = new ... stuffToDo.Add(myFirstMethod); stuffToDo.Add(mySecondMethod); foreach(var myDelegate in stuffToDo) { if(!GetStatus(ref status)) { Trace.WriteLine("Error"); return false; } myDelegate(ref status); } } 

For both good and bad, C # does not allow any other construction (for example, the preprocessor defines or such as we have in C ++).

+5
source

You can use exceptions, and let the exception extend up.

 void GetStatusAndException(ref Status) { if (!GetStatus(ref status))) Throw new Exception("Status exception"); } 

If you don’t want exceptions, you can’t do anything about it except putting everything except returning to the method:

 bool GetStatusAndTrace(ref Status) { bool result = GetStatus(ref status)) if (!result) Trace.WriteLine("Error"); return result; } bool Enable() { if (!GetStatusAndTrace(ref status)) return false; // do stuff if (!GetStatusAndTrace(ref status)) return false; // do more stuff if (!GetStatusAndTrace(ref status)) return false; // do even more stuff // 6 more times the above return true; } 
+1
source

A possible solution is to create a sanity shell for the API you are working with:

 class Wrapper { public void DoStuff() // Add static modifiers, parameters and return values as necessary { API.DoStuff(); CheckStatus(); } public void DoSomeOtherStuff() { API.DoSomeOtherStuff(); CheckStatus(); } private void CheckStatus() { Status status = default(Status); if(!GetStatus(ref status)) throw new InvalidStatusException(); } } 

Work a little, but it allows your client code to be more readable:

 bool Enable() { try { Wrapper.DoStuff(); Wrapper.DoSomeMoreStuff(); return true; } catch(InvalidStatusException) { Trace.WriteLine("Error"); return false; } } 
+1
source

Now you do not need to use exceptions, and you can still read. Regardless, you still have to call something. Exceptions are about 4000-8000 cycles.

 bool Enable() { if (GetStatus(ref status)) { // do stuff if (GetStatus(ref status)) { // do stuff if (GetStatus(ref status)) { // do stuff return true; } } } Trace.WriteLine("Error"); return false; } 
+1
source

With LINQ, you can do something like:

 delegate bool StatusFunc( ref int status ); bool Enable() { var funcs = new StatusFunc[] { GetStatusA, GetStatusB, GetStatusC }; return funcs.All( f => f( ref status ) ); } 

Please note that this is a bit hacked because GetStatus functions have side effects (status changes) that in LINQ queries are not no-no.

+1
source

How about this? This requires minimal changes to your existing code. yield return is your friend; let the compiler do all the dirty work:

 IEnumerable<bool> StatusChecks() { // Do stuff yield return GetStatus( ref status ); // Do stuff yield return GetStatus( ref status ); // Do stuff yield return GetStatus( ref status ); } bool Enable() { foreach ( var b in StatusChecks() ) { if ( !b ) { Trace.WriteLine("Error"); return false; } } return true; } 

or, if you don't mind a LINQ query with side effects, simply:

 bool Enable() { var result = StatusChecks().All( b => b ); if ( !result ) { Trace.WriteLine("Error"); } return result; } 
+1
source
 bool Enable() { try { if (!newProc } // do stuff if (!newProc } // do more stuff if (!newProc } // do even more stuff // 6 more times the above return true; } catch { return false; } } public function newProc() { if (!GetStatus(ref status)) { Trace.WriteLine("Error"); return false; } throw new Exception } 
0
source

Wrap the code in a try-catch block and rewrite GetStatus () to throw an exception on error. If you want to do this in a book, throw your own exception that inherits from System.Exception. Then you can also add the "status" property to the exception if you need this information later (for example, your code example is not specified).

Something like that:

 bool Enable() { try { GetStatus(ref status); // do stuff GetStatus(ref status); // do more stuff GetStatus(ref status); // do even more stuff // 6 more times the above return true; } catch (Exception ex) { Trace.WriteLine("Error"); return false; } } 

As I said, an exception thrown and caught should really be the usual exception, but the above will work.

0
source

Let's see if I understood correctly.

You can use the Specification design pattern: http://en.wikipedia.org/wiki/Specification_pattern

Instead of using validation, you should use something like an implementation of the above design pattern, as it provides you with a more extensible way to add rules regarding object states.

For example, you should define the "StatusSpecification" specification, which "does some things to verify that the status is correct." The result may be logical.

A damaged rule evaluator will take this logical result and make the necessary decisions (to exclude an exception? Try to restore the final application? Just notice the user about the error "Report an error?").

To summarize: you need to have some “specification loader” and execute the state of the object with respect to the loaded rules for the type of object. In the end, in this case, you will evaluate this state on one line (from the consumer's point of view), and perhaps your property flag may be the logical result.

0
source

Source: https://habr.com/ru/post/1270283/


All Articles