I have three if statements which they are apparently working on different functions. I wanted to combine them into one function, thus I have to combine the if statement. But I was stuck at how to use the || && and ().
My functions as filters, user can fill in whichever textboxes. On button click event, the code will find those that met criteria. Three of them work well independently, but combining them is very tough. Please bear with me and help me, I am just a very new programmer and no background at all. I am stuck for days. ;(
My filters snapshot:
First:
if (itemAuthor.ToLower() == txtComAuthor.Text.ToString().ToLower())
Second:
if ((!DateTime.TryParseExact(txtComStartDate.Text, "dd/MM/yy", provider, DateTimeStyles.AssumeLocal, out startDate)
|| DateTime.Parse(itemDate, provider, DateTimeStyles.AssumeLocal) >= startDate) &&
(!DateTime.TryParseExact(txtComEndDate.Text, "dd/MM/yy", provider, DateTimeStyles.AssumeLocal, out endDate)
|| DateTime.Parse(itemDate, provider, DateTimeStyles.AssumeLocal) <= endDate))
Third:
if (txtComKeyword1.Text != (String.Empty) && itemDescription.ToLower().Contains(txtComKeyword1.Text.ToLower()) ||
txtComKeyword2.Text != (String.Empty) && itemDescription.ToLower().Contains(txtComKeyword2.Text.ToLower()) ||
txtComKeyword3.Text != (String.Empty) && itemDescription.ToLower().Contains(txtComKeyword3.Text.ToLower()) ||
txtComKeyword4.Text != (String.Empty) && itemDescription.ToLower().Contains(txtComKeyword4.Text.ToLower()))
Whether to use || or && depends on whether you want the meaning at least one condition is true (use ||) or all conditions must be true (use &&).
If you need to mix both meanings, use () to cause conditions to be evaluated against each other, e.g.
if ( (a && b) || (c && d))
means if both a and b are true or both c and d are true.
It makes for easier-to-read and maintain code if you define separate booleans for each portion of the compound logic. There is no performance difference.
bool condition1 = !DateTime.TryParseExact(txtComStartDate.Text, "dd/MM/yy", provider, DateTimeStyles.AssumeLocal, out startDate);
bool condition2 = DateTime.Parse(itemDate, provider, DateTimeStyles.AssumeLocal) >= startDate);
bool condition3 = !DateTime.TryParseExact(txtComEndDate.Text, "dd/MM/yy", provider, DateTimeStyles.AssumeLocal, out endDate);
bool condition4 = DateTime.Parse(itemDate, provider, DateTimeStyles.AssumeLocal) <= endDate);
if ((condition1
|| condition2 &&
(condition3
|| condition4)
It will help you understand if you break each one of these clauses into functions and divvy up the complexity accordingly. Smaller pieces are easier to work with, and more maintainable in the long run. When you evolve as a programmer, you will eventually not use if statements for this at all, but rather leverage the power of polymorphism.
For now, begin by piecing things apart.
public void btnAnalyze_onClick(){
List<Item> results = new ArrayList<Item>();
if(txtComAuthor.Text != String.Empty)
{
List<Item> matched = filterByAuthor(txtComAuthor.Text);
results.addRange(matched);
}
if(txtComStartDate.Text != String.Empty)
{
List<Item> matched = filterByStartDate(txtComStartDate.Text);
results.addRange(matched);
}
// do the same for the others
return results;
}
public List<Item> filterByAuthor(String desiredAuthorName){
List<Item> matches = new ArrayList<Item>();
//have your data access piece here, from DB/Excel/whatever.
List<Item> candidates = ...
foreach(Item candidate in candidates){
if(candidate.ToLower() == desiredAuthorName){
matches.add(candidate)
}
}
return matches;
}
Experienced programmers will realize that there's a lot of duplication here and will have fits at the violations of DRY and performance. That's ok. It can be refactored. For a novice, this will be the easiest style to understand.
If you follow this style, it should be readily apparent where you need to do the filtering. Basically, you will need to replace the if statement in the foreach loop with the condition for the text field you're thinking about.
But you shouldn't need to add a bunch of clauses together doing this because you've broken things apart a little better. If you still find you need a few nested ifs, break it down further into even smaller functions.
When in doubt about logical grouping, put parentheses around every pair of operations. That way you know how the pairs will be combined.
if ((A && B) || (C && D)) will evaluate the (A && B) and (C && D) segments, then "or" those intermediate results together to produce the final value.
For further reading, search for commutative, associative, and distributive properties of boolean logic.
As far as I can tell, you want to evaluate all 3 at the same time, but simply adding them into one big line will be hard to read or maintain. I'd recommend setting seperate bool values for each of your previous ifs:
bool firstIf = (itemAuthor.ToLower() == txtComAuthor.Text.ToString().ToLower());
Then comparing all 3 in one statement:
if (firstIf && secondIf && thirdif)
{
Console.WriteLine("It works!");
}
This way, it is easier to make changes later if need be, and you can still read the code.
Related
I needed to implement a recursive method that checks whether an input is a palindrome or not. I was able to do this in one line and it works, but I'm not sure about how readable this is. I also keep getting a message "Simplify conditional ternary expression" but I'm not sure how
this is my code:
private static bool checkIfPalindrome(string i_InputToCheck, int i_StartIndex, int i_EndIndex)
{
return (i_StartIndex >= i_EndIndex) ? true : checkIfPalindrome(i_InputToCheck, i_StartIndex + 1, i_EndIndex - 1) && (i_InputToCheck[i_StartIndex] == i_InputToCheck[i_EndIndex]);
}
how readable this is
First off, naming convention: Get rid of unnecessary/uninformative parts of identifiers. For example, parameters do not need to start with i_ (presumably to denote “input”?). There’s no information conveyed here, and it adds noise. This has a huge impact on readability.
The logic itself can also be decluttered. The warning you’re getting gives you a hint that the condition can be simplified — this is always the case when your conditionals contain boolean literals.
More than anything, however, readability would benefit from breaking the expression up over multiple lines.
I would also swap the two secondary conditions, so that you first test the current characters, and then recurse further (only if the two currently tested characters are equal!):
private static bool IsPalindrome(string input, int start, int end) {
return (start >= end) ||
input[start] == input[end] &&
IsPalindrome(input, start + 1, end - 1);
}
This code relies on the correct precedence of && over ||. Some peope prefer making this operator precedence explicit by using more parentheses:
private static bool IsPalindrome(string input, int start, int end) {
return (start >= end) ||
(
input[start] == input[end] &&
IsPalindrome(input, start + 1, end - 1)
);
}
return i_StartIndex >= i_EndIndex || checkIfPalindrome(i_InputToCheck, i_StartIndex + 1, i_EndIndex - 1) && i_InputToCheck[i_StartIndex] == i_InputToCheck[i_EndIndex];
The simplification being prompted is because you're testing a boolean expression and then unnecessarily checking and returning it...
if (expression == true) is equivalent to if (expression) and
return expression ? true : false to return expression.
It is certainly not easy on the eye but I assume this is for a school exercise?
Take the following example:
A complex condition populates a variable printingStatus and it's really time demanding to discover if it happens. But it would be enough to monitor all the clients in the production environment to know if this code is used or not.
Is there any tool to implement this kind of Dynamic Code Analysis?
if (isOrdinatoPerCampionato && typeTable == 2
&& RowIndex > 0 && (!isNotUltimaRiga || isRigaDataMainHeader)
&& Condizione(rigaPrecedente, tournamentStatisticInfo, TournamentPrintingData))
{
printingStatus = PrintingStatus.Statistics;
TournamentPrintingData.Row = rigaPrecedente;
}
I have 3 booleans on my code (C#) and an int32 property that depends on what booleans are true and false.
Whats the best way to accomplish this in another way than if statements like:
if(a && b && !c)
d = 1;
if(a && !b && !c)
d = 2;
//etc.. ect...
EDIT: The 3 booleans must have every combination possible to set the int32 value.
EDIT 2: The value of "d" can be the same for two different boolean comparations.
It is better to capture the intent of the operation instead of explicitly check the boolean values.
For example:
public void Check()
{
if (HasOrdered())
{
// do logic
}
}
private bool HasOrdered()
{
return a && !b && !c;
}
private bool HasBooked()
{
return a && b && !c;
}
You could use a Karnaugh map to reduce your equations and have fewer ifs.
https://en.wikipedia.org/wiki/Karnaugh_map
I think what your doing now is perfectly fine and any other solutions would be down to preference.
My preference, where it applies would be to separate the checks out if possible.
if (!a)
return;
if (!b)
return;
if (!c)
return;
This would be useful in the event that you need to check certain prereqs before issuing a function, like if the user has logged in, if a parameter exists and is in the right context, along with other items.
Like i said this might not apply but i just wanted to voice my opinion
You could do the lookup table hint given by #Adriano, assuming you have lookup_table filled with values for index [0..8):
var index = new [] { a,b,c }.Aggregate(0, (a,i) => return 2*a + (i?1:0));
int d = lookup_table[index];
Edit The EDIT of the question made this irrelevant: What does d mean?
If it's the count of false values (possible from the sample code), make it
int d = new [] { a,b,c }.Count(b => !b);
I don't see anything wrong with how you're doing it, but if the output is the same for multiple conditions you may be able to simplify if by creating a truth table and simplifying the conditions.
For example, if d should be 0 anytime a is false you could simplify to:
if(a)
if(b && !c)
d = 1;
if(!b && !c)
d = 2;
...
else
d = 0;
Or if there is some mathematical pattern (e.g. a, b, and c represent the three digits of a binary number) then you could do bit arithmetic.
If, however, you have 8 distinct outcomes (one for each combination of a, b, and c) then your method is fine.
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.
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.