Finder for any IEnumerable

NHibernate requires you to use IList<T> properties a lot:

public IList<process> Processes { get; set; }

Searching through them is a real pain especially when you live in .NET 2.0 world:

public List<processModel> GetDeleted()
{
    List<process> list= new List<process>();
    foreach (Process process in this.Processes)
    {
        if (process.IsDeleted)
            list.Add(process);
    }
    return list;
}

If you can’t move your project to .NET 3.5 and use extension methods here’s the solution for you.

This is the simple class for making searches on any IEnumerable<T> easier:

public List<processModel> GetDeleted()
{
        return Finder.Create(this.Processes)
                .FindAll(x => x.IsDeleted);
}

Nice, isn’t it?

The Finder class itself:

public class Finder
{
    public static Finder<t> Create<t>(IEnumerable<t> list)
    {
        return new Finder<t>(list);
    }
};

public class Finder<t>
{
    private readonly IEnumerable<t> _list;

    public Finder(IEnumerable<t> list)
    {
        _list = list;
    }

    public T Find(Predicate<t> func)
    {
        foreach (T element in _list)
        {
            if (func(element))
                return element;
        }
        return default(T);
    }

    public List<t> FindAll(Predicate<t> func)
    {
        List<t> list = new List<t>();
        foreach (T element in _list)
        {
            if (func(element))
                list.Add(element);
        }
        return list;
    }

    public ReadOnlyCollection<t> FindAllAsReadOnly(Predicate<t> func)
    {
        return new ReadOnlyCollection<t>(this.FindAll(func));
    }

    public bool Contains(Predicate<t> func)
    {
        foreach (T element in _list)
        {
            if (func(element))
                return true;
        }
        return false;
    }
};

and some tests:

[TestFixture]
public class FinderTest
{
    [Test]
    public void FindAll_ForValueType()
    {
        List<int> list = new List<int> { 1, 2, 10, 12 };
        Finder<int> finder = Finder.Create(list);
        Assert.AreEqual(1, finder.FindAll(x => x == 1).Count);
    }

    [Test]
    public void FindAll_ForRefType()
    {
        List<box> list = new List<box> { new Box(1), new Box(1), new Box(15) };
        Finder<box> finder = Finder.Create(list);
        Assert.AreEqual(2, finder.FindAll(x => x.Id == 1).Count);
    }

    [Test]
    public void FindAllAsReadOnly_Find_ForRefType()
    {
        List<box> list = new List<box> { new Box(1), new Box(1), new Box(15) };
        Finder<box> finder = Finder.Create(list);
        ReadOnlyCollection<box> only = finder.FindAllAsReadOnly(x => x.Id == 1);
        Assert.AreEqual(2, only.Count);
    }

    [Test]
    public void Find_ForValueType()
    {
        List<int> list = new List<int> { 1 ,2, 10, 12 };
        Finder<int> finder = Finder.Create(list);
        Assert.AreEqual(1, finder.Find(x => x == 1));
        Assert.AreEqual(12, finder.Find(x => x == 12));
        Assert.AreEqual(0, finder.Find(x => x == 999));
    }

    [Test]
    public void Find_ForRefType()
    {
        List<box> list = new List<box> { new Box(21),  new Box(2),  new Box(15) };
        Finder<box> finder = Finder.Create(list);
        Assert.AreEqual(21, finder.Find(x => x.Id == 21).Id);
        Assert.AreEqual(2, finder.Find(x => x.Id == 2).Id);
        Assert.AreEqual(null, finder.Find(x => x.Id == 999));
    }

    [Test]
    public void Find_ForEmptyList()
    {
        Finder<box> finder = Finder.Create(new List<box>());
        Assert.IsNull(finder.Find(x => x.Id == 21));
        Assert.IsNull(finder.Find(x => x.Id == 2));
        Assert.IsNull(finder.Find(x => x.Id == 999));
    }

    internal class Box
    {
        readonly int _id;

        public int Id
        {
            get { return _id; }
        }

        public Box(int id)
        {
            _id = id;
        }
    }
} ;

Tags:

Questions?

Consider using our Q&A forum for asking questions.