An example of using a predicate to replace "if" in C #?

I read that the if keyword is evil and it is better to use a predicate to replace if. Then I googled but still don't get it.

Can anyone be kind to provide an example?

+2


source to share


5 answers


No matter what they say, if it's not evil. There may be specific cases for which a predicate is a better choice than an if (or a set of ifs).

For example,

 foreach (Foo f in fooList) {
     if (f.Equals(fooTarget)) {
        return f;
     }
 }

      

versus (.NET 2.0)



 fooList.Find(delegate (Foo f) { return f.Equals(fooTarget); });

      

or later)

 fooList.Find(f => f.Equals(fooTarget));

      

+9


source


They are just different. The predicate is more complex than a simple if statement. A predicate is basically a pointer to a method (delegate) that is bound to the type it takes as a parameter and returns true / false.

Imagine you are using generics and as a find method on generic lists, how can it know what types are in the list before your initialization. So the find method uses a predicate and does not know how the predicate will be implemented.

public T Find(Predicate<T> p)
    {
        //iterate through the collection and return the first match
        IEnumerator<T> enumerator = this.GetEnumerator();

        while (enumerator.MoveNext())
        {
            if (p(enumerator.Current))
            {
                return enumerator.Current;
            }
        }

        return default(T);
    }

      

The predicate is used in this case, but what (p (enumerator.Current)) actually evaluates about enumerator.Current is determined at the time of the predicate implementation. The code doesn't know what type T wil end up here.



Here are some ways to assign a predicate to a method

Predicate<string> findShortNames1 = x => x.Length == 3; // lambda expression
Predicate<string> findShortNames2 = delegate(string x) { return x.Length == 3; }; // anonymous method
Predicate<string> findShortNames3 = MatchOnShortNames; //existing method

// ...
private bool MatchOnShortNames(string s)
{
    return s.Length == 3;
}

      

Then the usage is like

someList.FindAll(findShortNames1);

      

+2


source


For example, whenever you have a loop like this:

List<Employee> retiredEmployees = new List<Employee>();
foreach (Employee employee in EmployeeList)
{
    if (employee.IsRetired)
        retiredEmployees.Add(employee);
}

      

Using a predicate, you will have to change it to:

retiredEmployees = EmployeeList.FindAll(e => e.IsRetired);

      

But I believe that in general the "if an assertion is considered evil" discussion, predicate

vs is if

simply referred to as a special use case of OOP and functional programming and procedural programming. This paradigm can be easily generalized to any delegate type (not just predicate) or any OOP use to replace conditional:

For example, if you go through your code, you can easily find code like this:

public class Employee
{
    private bool _isRetired;
    private double _amount;
    public double GetPayAmount()
    {
         if (_isRetired)
            return _amount * 0.9;
         else
            return _amount;
    }
}

      

Pure OOP advocates will tell you that you immediately need to fetch a different employee type and treat each branch as a different subtype, which removes the "evil if :"

public interface IEmployee
{
   double GetPayAmount();
}

public class Employee : IEmployee
{
   private double _amount;
   public double GetPayAmount()
   {
       return _amount;
   }
}

public class RetiredEmployee : IEmployee
{
   private double _amount;
   public double GetPayAmount()
   {
       return _amount * 0.9;
   }
}

      

Although the code is easier to maintain in this way, the amount of code in the second case is clearly doubled. For a simple hierarchy like this, there is little refactoring to do at this point. If you decide that you need many more special cases, then your conditional can get too complex and you can easily refactor it later.

+2


source


I don't use them for direct "if ... else" builds itself other than inn queries as it also removes the need for loop constructs. for example

int index = this.listObjects.FindIndex(x => x.PropertyA == objectItem.PropertyA);

      

or

List<ClassA> listClass = new List<ClassA>();

//... some more code filling listClass with ClassA types ...

ClassA tempClassA = listClass.FirstOrDefault().Where(x=> x.PropertyA == someValue);

      

I have to admit that if just one comparison is performed for one element, then I use the "if ... else" construction.

0


source


    static void Main()
    {
        string[] names = { "Lukasz", "Darek", "Milosz" };

        foreach (var item in names)
        {
            if (ContainsL(item))
                 Console.WriteLine(item);
        }

        string match1 = Array.Find(names, delegate(string name) { return name.Contains("L"); });
        //or
        string match2 = Array.Find(names, delegate(string name) { return name.Contains("L"); });
        //or
        string match3 = Array.Find(names, x => x.Contains("L"));


        Console.WriteLine(match1 + " " + match2 + " " + match3);     // Lukasz Lukasz Lukasz
    }
    static bool ContainsL(string name) { return name.Contains("L"); }

      

0


source







All Articles