Reducing if statements when calling other functions - c#

I have a function that calls a lot of other functions from different objects. Each function has to return true before calling the next one. As you can see I am using too many if statements. How can I improve the code and make it neater? Thanks
bool ISOKToDoSomthing()
{
boo retVal = false;
retVal = ObjA.CheckVersion(oldVersion);
if(retVal)
{
retVal = objB.CheckUserRight();
}
if(retVal)
{
retVal = ObjC.ISDBExist();
}
if(retVal)
{
retVal = OjbD.ISServerUp(ServerName);
}
//tons of similar code as above
.........
return retVal;
}

return
ObjA.CheckVersion(oldVersion) &&
objB.CheckUserRight() &&
ObjC.ISDBExist() &&
OjbD.ISServerUp(ServerName);

My advice: do nothing to this code without a clear business case for making the change.
Your code is clear, obvious, likely correct, easy to maintain and easy to debug. Why on earth would you want to change it in any way? Spend your time adding value by fixing bugs and adding features, not by changing working code unnecessarily. When your boss asks you "so what did you do today?" the answer should not be "I increased our schedule risk to by making unnecessary cosmetic changes to correct, working, already-debugged code".
Now, if there really is a problem here, the problem is likely not that the code is hard to read, but rather that the code rigidly encodes what ought to be a user-configurable business process. In that case, create an object called "Workflow" that encodes the business process, and an engine which evaluates an arbitrary workflow. Then construct an instance of that object that represents the desired workflow based on input from the user.
That actually adds value for the user; the user cares not a bit whether you use nested "if" statements or not.

if (!ObjA.CheckVersion(oldVersion)) return false;
if (!ObjB.CheckUserRight()) return false;
if (!ObjC.IsDBExist()) return false;
if (!ObjD.IsServerUp(serverName)) return false;
... your other checks ...
return true;
The short-circuiting of && is useful for a few conditions, but if you have "tons" of them, IMO that's way too much to try and stick in one statement.
A combination of the two might be useful, though. More useful still would be to condense some of these checks together into bigger chunks (but smaller than IsOKToDoSomething). For instance, check whether you have access to the database (whether it exists, whether you can log in to it, etc) all at once
Truth be told, the fact that you have so many objects to check hints at a design issue -- namely, you're trying to do too much at once, or you have a "god object" somewhere that has its little tentacles in every aspect of the system. You might want to look at fixing that.

return ObjA.CheckVersion(oldVersion) && objB.CheckUserRight() && ObjC.ISDBExist() && OjbD.ISServerUp(ServerName)

The && operator will short-circuit, so you can chain them like so:
bool ISOKToDoSomthing()
{
return
ObjA.CheckVersion(string oldVersion) &&
objB.CheckUserRight() &&
ObjC.ISDBExist() &&
OjbD.ISServerUp(ServerName) &&
//tons of similar code as above
.........
}

bool ISOKToDoSomthing()
{
return ObjA.CheckVersion(string oldVersion) &&
ObjB.CheckUserRight() &&
ObjC.ISDBExist() &&
OjbD.ISServerUp(ServerName);
}

Perhaps?
retVal = objB.CheckUserRight() && ObjC.ISDBExist() && OjbD.ISServerUp(ServerName);
etc.
A side note, you can test for example, if objB is null before calling a method on it in one statement (the code will break execution as soon as a condition has not been met, i.e. won't call the next condition) so you don't need lots of if(objB != null) type statements. E.g.:
retVal = (objB != null && objB.CheckUserRight()) && (ObjC != null && ObjC.ISDBExist()) && (OjbD != null && OjbD.ISServerUp(ServerName));

You can leverage the fact that C# does short-circuit evaluation:
return
ObjA.CheckVersion(oldVersion) &&
objB.CheckUserRight() &&
ObjC.ISDBExist() &&
OjbD.ISServerUp(ServerName);
Editing to fix syntax on CheckVersion's parameters

How about using and:
retVal = ObjA.CheckVersion(oldVersion) &&
objB.CheckUserRight() &&
ObjC.ISDBExist() &&
OjbD.ISServerUp(ServerName);
return retval;

To make the code less wordy, you could try a while loop. Given that your method here is to not ever change the value of your original value if it /ever/ turns false, then it would be while(retval) {} and iterate over a list of actions. Personally, I think this is ugly. Consider using a switch, or even (yuck on this, but it would work) a bitwise enum.
From my perspective, when I see myself writing code like this, I've made a grave architectural mistake somewhere and I should really rethink the reason behind making this call. Perhaps you should take another look at your logic, rather than just your code. Sit down and draw some boxes and work a bit more in the design phase and you might find yourself building things very differently.
edit: or yeah, like everyone else did, you can make your iteration a single if statement. Again, this is a bigger problem than a long list of booleans.

It depends on how much you want to change. Perhaps instead of returning a bool from your sub-methods, you could throw an exception.
bool retVal = true;
try
{
ObjA.CheckVersion(oldVersion);
objB.CheckUserRight();
ObjC.ISDBExist();
OjbD.ISServerUp(ServerName);
}
catch (SomeException ex)
{
// Log ex here.
retVal = false;
}
return retVal;
If you do something like this, IsDBExist probably isn't the best name (since Is generally translates to "returns a bool" in my mind), but you get the picture.

Related

c# which is the better way to declare two parameters

I have a very quick question about the best way to use two variables. Essentially I have an enum and an int, the value for which I want to get within several ifs. Should I declare them outside the if's or inside - consider the following examples:
e.g.a:
public void test() {
EnumName? value = null;
int distance = 0;
if(anotherValue == something) {
distance = 10;
value = getValue(distance);
}
else if(anotherValue == somethingElse) {
distance = 20;
value = getValue(distance);
}
if (value == theValueWeWant){
//Do something
}
OR
e.g.2
public void test() {
if(anotherValue == something) {
int distance = 10;
EnumType value = getValue(distance);
if (value == theValueWeWant){
//Do something
}
else if(anotherValue == somethingElse) {
int distance = 20;
EnumType value = getValue(distance);
if (value == theValueWeWant){
//Do something
}
}
I am just curious which is best? or if there is a better way?
Purely in terms of maintenance, the first code block is better as it does not duplicate code (assuming that "Do something" is the same in both cases).
In terms of performance, the difference should be negligible. The second case does generate twice as many locals in the compiled IL, but the JIT should notice that their usage does not overlap and optimize them away. The second case is also going to cause emission of the same code twice (if (value == theValueWeWant) { ...), but this should also not cause any significant performance penalty.
(Though both aspects of the second example will cause the compiled assembly to be very slightly larger, more IL does not always imply worse performance.)
Both examples do two different things:
Version 1 will run the same code if you get the desired value, where as Version 2 will potentially run different code even if you get the desired value.
There's a lot of possible (micro)optimizations you could do.
For Example, if distance is only ever used in getValue(distance), you could get rid of it entirely:
/*Waring, micro-optimization!*/
public void test() {
EnumType value = getValue((anotherValue == something) ? 10 : (anotherValue == somethingElse) ? 20 : 0);
if (value == theValueWeWant){
//Do something
}
}
If you wish to use those later on, then g for the second method. Those variables will be lost as soon as they're out of scope.
Even if you don't want to use them later, declaring them before the if's is something you should do, to avoid code repetition.
This question is purely a matter of style and hence has no correct answer, only opinions
The C# best practice is generally to declare variables in the scope where they are used. This would point to the second example as the answer. Even though the types and names are the same, they represent different uses and should be constrained to the blocks in which they are created.

Which is the best practices: MethodReturnsBoolean == true/false OR true/false == MethodReturnsBoolean

I have been writing:
if(Class.HasSomething() == true/false)
{
// do somthing
}
else
{
// do something else
}
but I've also seen people that do the opposite:
if(true/false == Class.HasSomething())
{
// do somthing
}
else
{
// do something else
}
Is there any advantage in doing one or the other in terms of performance and speed? I'm NOT talking about coding style here.
They're both equivalent, but my preference is
if(Class.HasSomething())
{
// do something
}
else
{
// do something else
}
...for simplicity.
Certain older-style C programmers prefer "Yoda Conditions", because if you accidentally use a single-equals sign instead, you'll get a compile time error about assigning to a constant:
if (true = Foo()) { ... } /* Compile time error! Stops typo-mistakes */
if (Foo() = true) { ... } /* Will actually compile for certain Foo() */
Even though that mistake will no longer compile in C#, old habits die hard, and many programmers stick to the style developed in C.
Personally, I like the very simple form for True statements:
if (Foo()) { ... }
But for False statements, I like an explicit comparison.
If I write the shorter !Foo(), it is easy to over-look the ! when reviewing code later.
if (false == Foo()) { ... } /* Obvious intent */
if (!Foo()) { ... } /* Easy to overlook or misunderstand */
The second example is what I've heard called "Yoda conditions"; "False, this method's return value must be". It's not the way you'd say it in English and so among English-speaking programmers it's generally looked down on.
Performance-wise, there's really no difference. The first example is generally better grammatically (and thus for readability), but given the name of your method the "grammar" involved (and the fact you're comparing bool to bool) would make the equality check redundant anyway. So, for a true statement, I would simply write:
if(Class.HasSomething())
{
// do somthing
}
else
{
// do something else
}
This would be incrementally faster, as the if() block basically has a built-in equality comparison, so if you code if(Class.HasSomething() == true) the CLR will evaluate if((Class.HasSomething() == true) == true). But, we're talking a gain of maybe a few clocks here (not milliseconds, not ticks, but clocks; the ones that happen 2 billion times a second in modern processors).
For a false condition, it's a toss-up between using the not operator: if(!Class.HasSomething()) and using a comparison to false: if(Class.HasSomething() == false). The first is more concise, but it can be easy to miss that little exclamation point in a complex expression (especially since it occurs before the entire expression) and so I'd consider equating with false to ensure that the code is readable.
You will not see any performance difference.
The correct option is
if (Whatever())
The only time you should write == false or != true is when dealing with bool?s. (in which case all four options have different meanings)
You will not see any performance difference, either comparison is translated into the same IL...
if(Class.HasSomething())
{
// do somthing
}
is my way. But better try to avoid a multiple method call of HasSomething(). Better expose the return value once and reuse it.
you should write neither.
Write
if(Class.HasSomething())
{
// do something
}
else
{
// do something else
}
instead. If Class.HasSomething() is already a bool, it's pointless to compare it to another boolean
There is no perf advantage here. This coding style is used to guard against situation where programmer types = instead of ==. Compiler will cathc this because true/false are constants and cannot be assigned a new value
For the case of booleans, I'd recommend neither: just use if (method()) and if (!method()). For the case of things besides booleans, the convention of using yoda-speak, e.g. if (1 == x) came about to prevent mistakes, because if (1 = x) will throw a compiler error while if (x = 1) will not (it is valid code in C, but is probably not what you intended). In C#, such a statement is only valid if the variable was a boolean, which reduces the need to do that.

How to Exit a Method without Exiting the Program?

I am still pretty new to C# and am having a difficult time getting used to it compared to C/CPP.
How do you exit a function on C# without exiting the program like this function would?
if (textBox1.Text == "" || textBox1.Text == String.Empty || textBox1.TextLength == 0)
textBox3.Text += "[-] Listbox is Empty!!!!\r\n";
System.Environment.Exit(0);
This will not allow return types and if left alone it will keep going on through the function unstopped. Which is undesirable.
There are two ways to exit a method early (without quitting the program):
Use the return keyword.
Throw an exception.
Exceptions should only be used for exceptional circumstances - when the method cannot continue and it cannot return a reasonable value that would make sense to the caller. Usually though you should just return when you are done.
If your method returns void then you can write return without a value:
return;
Specifically about your code:
There is no need to write the same test three times. All those conditions are equivalent.
You should also use curly braces when you write an if statement so that it is clear which statements are inside the body of the if statement:
if (textBox1.Text == String.Empty)
{
textBox3.Text += "[-] Listbox is Empty!!!!\r\n";
}
return; // Are you sure you want the return to be here??
If you are using .NET 4 there is a useful method that depending on your requirements you might want to consider using here: String.IsNullOrWhitespace.
You might want to use Environment.Newline instead of "\r\n".
You might want to consider another way to display invalid input other than writing messages to a text box.
In addition to Mark's answer, you also need to be aware of scope, which (as in C/C++) is specified using braces. So:
if (textBox1.Text == "" || textBox1.Text == String.Empty || textBox1.TextLength == 0)
textBox3.Text += "[-] Listbox is Empty!!!!\r\n";
return;
will always return at that point. However:
if (textBox1.Text == "" || textBox1.Text == String.Empty || textBox1.TextLength == 0)
{
textBox3.Text += "[-] Listbox is Empty!!!!\r\n";
return;
}
will only return if it goes into that if statement.
I would use return null; to indicate that there is no data to be returned
The basic problem here is that you are mistaking System.Environment.Exit for return.
#John, Earlz and Nathan. The way I learned it at uni is: functions return values, methods don't. In some languages the syntax is/was actually different. Example (no specific language):
Method SetY(int y) ...
Function CalculateY(int x) As Integer ...
Most languages now use the same syntax for both versions, using void as a return type to say there actually isn't a return type. I assume it's because the syntax is more consistent and easier to change from method to function, and vice versa.
If the function is a void, ending the function will return. Otherwise, you need to do an explicit return someValue. As Mark mentioned, you can also throw an exception.

Improve readability of a short snippet while keeping StyleCop happy

The code below looked ok to me when I wrote it, but when I came back to it again, it was pretty hard to grasp what is going on. There used to be parenthesis around value == ..., but I had to remove them after StyleCop became mandatory (I cannot really control this). So, how can I improve this section of code? I was thinking: x = value == y ? true : false;, but that probably is even more confusing, plus silly, although compiler will optimize that.
set
{
Debug.Assert(value == ConfigType.DATABASE || value == ConfigType.FILE,
"Configuration type must be either 'File-based' or 'Database-based'; it was: "
+ value.ToString());
// HG TODO: The following is concise but confusing.
this.fileBasedRadioButton.Checked = value == ConfigType.FILE;
this.databaseBasedRadioButton.Checked = value == ConfigType.DATABASE;
}
bool isFile = value == ConfigType.FILE;
bool isDatabase = value == ConfigType.DATABASE; // or isDatabase = !isFile
Debug.Assert(isFile || isDatabase,
"Configuration type must be either 'File-based' or 'Database-based'; it was: "
+ value.ToString());
this.fileBasedRadioButton.Checked = isFile;
this.databaseBasedRadioButton.Checked = isDatabase;
This makes it a little more readable (explicitly declaring the bool), you know it has to be true or false.
And this way, if you need to (maybe in the future) change settings based on file/database in the same method, you already have the bool handy, instead of checking each time
If you don't want to use the ?: operator use if..else. Sure it is a little more verbose, but you wont spend more than a few seconds figuring it out.
A few months from now when you revisit this code you will be glad you took an extra 5 lines.
Making code easy to maintain should be your #1 priority.
if (value == ConfigType.FILE)
this.fileBasedRadioButton.Checked = true;
else
this.fileBasedRadioButton.Checked = false;
if (value == ConfigType.DATABASE)
this.databaseBasedRadioButton.Checked = true;
else
this.databaseBasedRadioButton.Checked = false;
Indent the second and third line of the Debug.Assert() method. It should then look like this:
Debug.Assert(value == ConfigType.DATABASE || value == ConfigType.FILE,
"Configuration type must be either 'File-based' or 'Database-based'; it was: "
+ value.ToString());
I know this is really a minor stylistic alteration, but I've always found when I have to pass a lot of arguments or have some really long statement, when I carry over to a newline I should indent before the ;.
It prevents the Debug.Assert() from looking like 3 lines.
As for the value==, I agree with the previous poster. You should make a bool isDatabase and isFile to prevent calling a field from ConfigType twice in your first arg.

Is the method that I am using for retrieval in my generic list optimized

At some time there will be a large amount of records, about 50,000.
with that in mind is the method GetEquipmentRecord up to the task.
thanks for you opinions.
c# ,net 2,0
public enum EquipShift { day, night };
public class EquipStatusList : List<EquipStatus>
{
string SerialFormat = "yyyyMMdd";
int _EquipmentID;
string _DateSerial;
EquipShift _Shift;
public EquipStatus GetEquipmentRecord(int equipmentID, EquipShift shift,
DateTime date)
{
_DateSerial = date.ToString(SerialFormat);
_Shift = shift;
_EquipmentID = equipmentID;
return this.Find(checkforEquipRecord);
}
bool checkforEquipRecord(EquipStatus equip)
{
if ((equip.EquipmentID == _EquipmentID)
&& (equip.Shift == _Shift)
&& (equip.Date.ToString(SerialFormat) == _DateSerial))
return true;
else
return false;
}
}
update :
I have changed the evaluation to read
if ((equip.Date.Date == _date.Date) && (equip.EquipmentID == _EquipmentID) && (equip.Shift == _Shift) )
not sure it that helps
Without commenting on your choice of algorithm, we can say that it probably is optimized enough.
You've got an O(n) find() in there; searching a sorted list with a binary search would be O(lg n) and searching a hash-set (or Dictionary in C# 2.0) would be O(1) for example. Hash-set would obviously be the way to go if you were calling this function often.
But bottlenecks are rarely where you expect them, so that you ask the question on this particular instance means that, on balance, profiling later will actually show that the big slowdowns are elsewhere.
You could speed this up considerably by implementing a suitable GetHashCode method and using a System.Collections.Generic.HashSet<EquipStatus> as the backing container. However, as it's not entirely clear how you are using your class (i.e. which other List<T> methods you use), ymmv.
No, it is not. Your whole construct is not able to be used in a multitasking environment. You are storing the details to search for as instance members of the class. I would take advantage of PLINQ (Parallel Linq) and the usual operators, also I wouldn't derive from the List itself, but offer an extension method like this:
public static EquipStatus GetEquipmentRecord(this IEnumerable<EquipStatus> list, int equipmentID, EquipShift shift, DateTime date)
{
return list.AsParallel().FirstOrDefault(e => e.EquipmentID == equipmentID && e.Shift == shift, e.Date.Date == date.Date);
}
By this, multiple searches at the same time are possible.
well an obvious way to improve your checkForEquipRecord method is to change
if ((equip.Date.Date == _date.Date) && (equip.EquipmentID == _EquipmentID) && (equip.Shift == _Shift) )
return true;
else
return false;
to just return (equip.Date.Date == _date.Date) && (equip.EquipmentID == _EquipmentID) && (equip.Shift == _Shift)
As far as efficiency goes, it might already be an optimization that the JIT compiler makes.

Categories