Tuesday, April 1, 2008

Generics List<T>.FindAll (to filter)

Since 2.0, generics were one of my favorites. Use them quite a bit in my object models. And with that comes the need for iterative operations. One such being using FindAll to get filtered results using some sort of criteria. While generic predicates is one way to do it (for well defined filters), I also use anonymous delegate to do filtering dynamically (like based on name, for example). Let's look at either one.

Say we have a Product class and we get a List as available products to be shown to the user. Say we have an attribute (enumeration) for each product that determines its category. In a simple scenario, I have a well defined set of limited categories and I define predicates to do the filtering. And for some dynamic filtering, I'm using anonymous delegate to do the filtering. Take a look:

/// <summary>

/// An example to show generic predicates

/// </summary>

[Serializable]

public class myProduct

{

/// <summary>

/// ProductCategory

/// </summary>

public enum ProductCategory

{

General = 1,

Speciality = 2

}

private string _Name = string.Empty,

_ProductID = string.Empty;

private ProductCategory _Category;

public string Name

{

get { return _Name; }

set { _Name = value; }

}

public string ProductID

{

get { return _ProductID; }

set { _ProductID = value; }

}

public ProductCategory Category

{

get { return _Category; }

set { _Category = value; }

}

public myProduct() { }

#region "Predicate for Filters"

/// <summary>

/// Predicate for General Products

/// </summary>

/// <param name="p"></param>

/// <returns></returns>

private static bool GeneralProducts(myProduct p)

{

return (p.Category == myProduct.ProductCategory.General);

}

/// <summary>

/// Predicate for Speciality Products

/// </summary>

/// <param name="p"></param>

/// <returns></returns>

private static bool SpecialityProducts(myProduct p)

{

return (p.Category == myProduct.ProductCategory.Speciality);

}

/// <summary>

/// Filter and return General Products

/// </summary>

/// <param name="productList"></param>

/// <returns></returns>

public static List<myProduct> GetGeneralProducts(List<myProduct> productList)

{

return productList.FindAll(GeneralProducts);

}

/// <summary>

/// Filter and return Speciality Products

/// </summary>

/// <param name="productList"></param>

/// <returns></returns>

public static List<myProduct> GetSpecialityProducts(List<myProduct> productList)

{

return productList.FindAll(SpecialityProducts);

}

#endregion "Predicate for Filters"

/// <summary>

/// Anonymous delegate to filter

/// </summary>

/// <param name="productList"></param>

/// <param name="nameLike"></param>

/// <returns></returns>

public static List<myProduct> GetProductsNamedLike(List<myProduct> productList, string nameLike)

{

return productList.FindAll(delegate(myProduct p) { return p.Name.Contains(nameLike); });

}

}


We will find a lot of discussion and explanation about this topic, but this is my simplified case to show the usage.

Love coding!

5 comments:

Anonymous said...

Superb. Thanks for such a nice article. Great Help

Unknown said...

Thanks buddy. It worked like wonders.

neha said...

good examples

Anonymous said...

Fantastic! A little bit more comments whould be wellcome, but it´s really a good example.

Kunal said...

Great Article, Thanks