C# Tips – Using delegate in List.Find() predicate

If we had a funcional language (eg or ), we could easily manage a collection or list.
With the , we can work equally functional with (Exploring). using this feature of the we can develop, process and manage our data more easly, especially with .

An example that I wish to use, and is also the most frequent that I happened to develop, is the use of these anonymous delegates to the search function of a generic list ()

Instead of writing code with foreach loops every time I need to find an element in a set, I use a predicate that does the job in my place, so I can keep the code cleaner and I can focus on “things” more interesting.

The easiest way to use the Find() method with a Predicate is included in this code:

public class person
{
    public int Anni { get; set; }
    public string Nome { get; set; }
    public person(int anni, string nome)
    {
        this.Anni = anni;
        this.Nome = nome;
    }
}

 

//I assume I have a non-empty list
List<person> agenda = new List<person>();
/* .. load objects from DataBase .. */

//I create a simple search criteria
string personToBeSearched = "mario";
person mario = agenda.Find(delegate(person p) { return p.Nome == personToBeSearched; });

Using the () instead, introduced in the , the code is reduced even more:

//I assume I have a non-empty list
List<person> agenda = new List<person>();
/* .. load objects from DataBase .. */

//I create a simple search criteria
string personToBeSearched = "mario";
person mario = agenda.Find(p => p.Nome == personToBeSearched;);

You can also write an explicit predicate, if you do not like seeing too terse code:

private static bool findTeen(person p)
{
    if (p.Anni < 18)
        return true;
    return false;
}

List<person> BlockBuster_GameOnly = agenda.findAll(findTeen);

We can refine even more the code to take advantage of this methodology does not only for the Find() method, but also to other cases of use. Indeed, we can expand our class that represents the data by overriding the Equals() method, as in that other C# example:

public class person
{
    public int Anni { get; set; }
    public string Nome { get; set; }
    public person(int anni, string nome)
    {
        Anni = anni;
        Nome = nome;
    }
    public override bool Equals(object obj)
    {
        if (obj == null) return false;

        person p2 = obj as person;
        if ((object)p2 == null) return false;

        return (this.Anni == p2.Anni) && (this.Nome == p2.Nome);
        //return (this.Anni.Equal(p2.Anni)) && this.Nome.Equal(p2.Nome));
    }
    public override bool Equals(person p2)
    {
        if ((object)p2 == null) return false;

        return (this.Anni == p2.Anni) && (this.Nome == p2.Nome);
        //return (this.Anni.Equal(p2.Anni)) && this.Nome.Equal(p2.Nome));

    }
    public override int GetHashCode()
    {
        return this.Anni ^ this.Nome.Length;
    }
}

In this way, we can not just do a search based on a single property, but also look for “entities” within a specific list:

person Glauco = new person(36, "Glauco");
if (agenda.Find(p => p.Equals(Glauco)) == null)
    agenda.Add(Glauco);

As you can see from the code, can be very intuitive and easy to write lambda expressions in simple cases like these, but what happens if we have lists that contain very complex objects? For example an object that identifies a testCrash of a passenger car, or an object that represents a measurement of a numerical control system for an assembly line, rather than for the detection data of a station’s gas plant.
These objects may be very complex and the code becomes almost unreadable.
Better to opt for the explicit predicates version. But even in this case we write a predicate for each different search criteria or for any sort order that we may serve.

We solve by creating a “class predicate” that allows parameters and displays the search method. In this way we can drastically reduce the predicates that we have to write (although it will be virtually impossible to reduce us to one). We also see a simple example for this case (not to complicate this article) always written in C#:

private class EnvironmentMonitoringResult
{
    //...
    //...
    //...
}

private enum CostructormanagerType
{
    gasMetano = 0,
    gasButano,
    //...
    //...
}

private class myPredicate
{
    private CostructormanagerType impianto;
    private bool dummy;
    private string Parametro1;
    //...
    //...
    //...

    public myPredicate(CostructormanagerType type)
    {
        this.impianto = type;
    }
    public myPredicate(CostructormanagerType type, bool isDummy)
    {
        this.impianto = type;
        this.dummy = isDummy;
    }
    public bool findTipo1(EnvironmentMonitoringResult risultatoMisurazione)
    {
        bool findOK = true;
        switch (this.impianto)
        {
            case CostructormanagerType.gasMetano:
                findOK &= risultatoMisurazione.isNotturno = this.dummy;
                findOK &= risultatoMisurazione.Parametro1 = this.Parametro1;
                //...
                //altri controlli
                break;
            case CostructormanagerType.gasButano:
                break;
            default:
                break;
        }
        //...
        //altri controlli
        return findOK;
    }
    public bool findTipo2(EnvironmentMonitoringResult risultatoMisurazione)
    { ... ... }
}

List<EnvironmentMonitoringResult> misurazioniMensili = new List<EnvironmentMonitoringResult>();

myPredicate ricercaCaso1 = new myPredicate(CostructormanagerType.gasButano, false);

//ricercaCaso1.ParametroX = qualcheCosa
EnvironmentMonitoringResult controlloAllarmeNotturno = misurazioniMensili.Find(ricercaCaso1.findTipo1);

//ricercaCaso1.ParametroY = qualcheCosaAltro
//ricercaCaso1.ParametroZ = stoInventando
EnvironmentMonitoringResult controlloCrashZonaAlfaX = misurazioniMensili.Find(ricercaCaso1.findTipo2);

You can see that even complex searches can be enclosed in a single class and maybe implemented in a separate layer (eg EnvironmentService), separate from any interface or BusinessLogic.

Points of interest

Just as we used anonymous delegates for the Find() method and FindAll() method, we can expand our class by implementing the interface and use the predicates (or Lambda expressions) for the Sort() method too.

Advertisements

One comment on “C# Tips – Using delegate in List.Find() predicate

  1. this is nice to understand the delegates thanks a lot 🙂
    I need more explanation for this and why this came in to picture and where in real life we use it .

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s