Romasz
Romasz

Reputation: 29792

Generic method using List dependant on type

I've an interface and two classes:

public interface IIdent
{
   int Id { get; set; }
}

public class First : IIdent
{
   public int Id { get; set; }
   public string Name;
}

public class Second : IIdent
{
   public int Id { get; set; }
   public string Surname;
}

Now I want to make a third class with two Lists of types First and Second, and write one method which will search specific List depending on type:

public class myClass
{
   List<First> firstItems;
   List<Second> secondItems;

    public int SearchOf<T>(T pattern) where T : IIdent
    {
        List<T> searched;
        if (pattern is First) searched = firstItemsas List<T>;
        else if (pattern is Second) searched = secondItems as List<T>;
        else return -1;
        for (int index = 0; index < searched.Count; index++)
            if (pattern.Id == searched[index].Id)
                return index;
        return -1;
    }
}

The code above works, but could it be done easier - that the method would search specific List depending on the type of pattern?

Upvotes: 0

Views: 70

Answers (2)

Jevgeni Tsaikin
Jevgeni Tsaikin

Reputation: 321

I would rather do a generic MyClass instead. Something like:

public class MyClass<T> where T : IIdent
{
    IList<T> items = new List<T>();

    public int SearchOf(T pattern)
    {
        for (int index = 0; index < items.Count; index++)
            if (pattern.Id == items[index].Id)
                return index;
        return -1;
    }
}

Later "First" and "Second" can have their own implementation of MyClass instead of putting both collections into a single MyClass instance. Keeping one collection in one instance of MyClass is a better practice.

And when you are going to search you do something like:

void Main()
{
    Search<First>(new First() { Id = 1 });
}

void Search<T>(T pattern) where T : IIdent
{
    var myClass = new MyClass<T>();
    myClass.SearchOf(pattern);
}

Afterwards you can easily add support for Third etc.

Upvotes: 0

Lasse V. Karlsen
Lasse V. Karlsen

Reputation: 391664

In this case I wouldn't expose the generic method, I would do this:

public class myClass
{
    List<First> firstItems;
    List<Second> secondItems;

    public int SearchOf(First pattern)
    {
        return SearchOf(pattern, firstItems);
    }

    public int SearchOf(Second pattern)
    {
        return SearchOf(pattern, secondItems);
    }

    private static int SearchOf<T>(T pattern, IList<T> searched) where T : IIdent
    {
        for (int index = 0; index < searched.Count; index++)
            if (pattern.Id == searched[index].Id)
                return index;
        return -1;
    }
}

This has the added benefit of not allowing a call to SearchOf with anything but a First or a Second object, even if it implements IIdent.

I'm also a proponent of avoiding making methods too specific, so here's an alternative version:

public int SearchOf(First pattern)
{
    return SearchOf(pattern.Id, firstItems);
}

public int SearchOf(Second pattern)
{
    return SearchOf(pattern.Id, secondItems);
}

private static int SearchOf(int id, IEnumerable<IIdent> searched)
{
    int index = 0;
    foreach (var ident in searched)
    {
        if (ident.Id == id)
            return index;
        index++;
    }
    return -1;
}

Upvotes: 4

Related Questions