Search code examples
c#listpredicate

Is it possible to create in C# a predicate with a custom values, or templated values


I am relatively new to C# and come from a C++ background. I have been looking a list searches and the usages of Find.

I am trying to define a function that takes a parameter, and returns an entry from a list. for example

class Product
{
    public string id;
    public string description;
}

public List<Product> products = new List<Product>();
// Add some items to the list

My question is, can I turn this following custom "Find" function using C# features like Predicates/Funcs

Product GetProductByID(string id)
{
    foreach (Product p in products)
    {
        if (p.id == id)
        {
            return p;
        }
    }
}

I have tried using Predicates, but I don't seem to be able to find anyway to feed a value in to the function to do the boolean expression check against. I understand how I would write a Predicate to find a speciic item in a list, but not a dynamic one that could be passed in.

Ideally I would then like to go one step further and Template it so the Predicate could be used for any list of items that have a similar structure.

i.e if we also had

class Employee
{
    public string id;
    public int age;
}

public List<Employee> employees = new List<Employee>();
// Add some items to the list

It would be really cool to use the same defined Predicate, but on this list of a totally different type. Ie something like

// psudo
Predicate<T, string> predicate = return <T>.id == id;

and it work because T is always of a type that has a string member called id

I Hope that all makes sense.


Solution

  • I understand how I would write a Predicate to find a speciic item in a list, but not a dynamic one that could be passed in.

    This is where lambda expressions come in, allowing you to create an instance of a delegate type that capture variables in scope. For example:

    public Predicate<Product> CreateProductPredicateForId(string id)
    {
        return product => product.id == id;
    }
    

    Now in terms of making that generic, you'd need to have an interface that specifies an Id property. You can then write a generic method. For example:

    public interface IEntity
    {
        string Id { get; }
    }
    ...
    
    public Predicate<T> CreatePredicateForId<T>(string id) where T : IEntity
    {
        return entity => entity.Id == id;
    }