简体   繁体   中英

Building Complicated If-Statement

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, eg

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM