# Getting list items

Is there any possibility of refactoring this code?

In class A:

public List<Item> GetItems() {
var result = new List<Item>();
foreach(var item in repo.GetItems1()) {
var x = repo.GetOtherItems1(item.Id, "param1", param2); // this part is different
if (x.Value > 5)
}

return result;
}


In class B:

public List<Item> GetItems() {
var result = new List<Item>();
foreach(var item in repo.GetItems2()) {
var x = repo.GetOtherItems2(param1, param2, item.Id); // this part is different
if (x.Value > 5)
}

return result;
}


I tried to use template method, but due to other params in GetOtherItemsX(...), is it now possible?

• Is it the same repository type you are work with in both classes? Otherwise it doesn't make much sense to try and re-work. – WestDiscGolf Dec 12 '11 at 11:04

Well, you could receive a delegate for getting the elements - that is, to make the action that is different:

public List<Item> GetItems(Func<Item, Repository> getOtherItems) {
if( getOtherItems == null ) {
throw new ArgumentException();
}
var result = new List<Item>();
foreach(var item in repo.GetItems2()) {
var x = getOtherItems();
if (x.Value > 5)
}

return result;
}


And then you could call it like so:

// In class A
this.GetItems( repo => repo.GetOtherItems1(item.Id, "param1", param2) );

// In class B
this.GetItems( repo => repo.GetOtherItems2(param1, param2, item.Id) );


But I notice that you also use repo.GetItems1() in A and repo.GetItems2() in B.
So the difference you pointed out is not the only one.

With this in mind, I would advise rethinking your class structure. These two could inherit from the same base class, and merely extend it. (Or it could be polymorphism, or...)

Maybe:

public interface IMyList<Item>
{
List<int> GetItems();
// If it returns a single item, the name should NOT be pluralized!!
Item GetOtherItems();
}


Or maybe an abstract class?

edit: read @JoeGeeky 's comment on the performance impact of using delegates; this may become relevant if the delegate is used on a very intensive cycle or under high loads.

• I like the idea of a base abstract class which has the GetItems method and then the classes which implement it can pass in the desired Func<>. – WestDiscGolf Dec 12 '11 at 12:58
• These are not bad ideas but will come with a performance penalty... You didn't mention this as an issue, but it's worth considering. – JoeGeeky Dec 17 '11 at 23:11
• @JoeGeeky What comes with performance penalty, using the delegate? Would this penalty be addressed by instead deriving from an interface or abstract class? – ANeves Dec 19 '11 at 10:04
• Invoking a method (especially an inlined method) is substantially cheaper then invoking a delegate chain with one subscribed member. By way of example... invoking an inlined instance method costs ~0.2ns while invoking a delegate costs ~41ns. The numbers will vary depending on your hardware but the relative difference will essentially remain the same. Func<> and Action<> invokations have very similar costs. If this is occuring in tight loops or high loads, this can start to add up. – JoeGeeky Dec 19 '11 at 10:17

I would make a couple suggestions:

• Consider making the return type of your GetItems methods IEnumerable<Item>, ICollection<Item>, or IList<Item>, depending on how you intend to use the result of your function. This will make refactoring later easier.
• Consider renaming your repo.GetOtherItemsN methods. Their names suggest that multiple items are being returned rather than a single item, but they appear to be returning single items. (ANeves mentions this in the comments for his interface)
• Consider updating the signature of both your repo.GetOtherItemsN methods to take in parameters in a similar order. It seems strange that one takes in Id, then param1 (as a string), then param2, while the other takes in param1 (unknown type), then param2, then Id. Id should probably come first.
• Consider using a constant/enum value in place of 5 within your if (x.Value > 5) statements. If both classes A and B have a common base class (suggested, given the other answers), I would put it there.
• Building on ANeves answer, I would also pass in an IEnumerable<Item> parameter to the GetItems function, since you use repo.GetItems1 versus repo.GetItems2 in the two classes and you do not do anything more involved than enumerating the collection.

If you are a LINQ-fan, you could also transform this to a LINQ statement:

public IEnumerable<Item> GetItems(IEnumerable<Items> source, Func<Item, Repository> getOtherItems)
{
if (getOtherItems == null)
{
throw new ArgumentException();
}
var result = from item in source
let x = getOtherItems()
where x.Value > MIN_VAL
select x;
}


If you need it evaluated early rather than lazy-loaded, you just need to toss on a .ToList () or .ToArray() before returning.

After taking Dan and the others suggestions for cleaning up the repository interface, you could also have some benefit from using a common expression for a Linq where statement.

[TestMethod]
public void CanUseCommonWhereExpression()
{
var repo = SetupRepo();

Assert.AreEqual(1, GetItems1(repo).Where(ValueMoreThan(5)).Count());
Assert.AreEqual(2, GetItems2(repo).Where(ValueMoreThan(5)).Count());
Assert.AreEqual(
2,
GetItems2(repo).AsQueryable().Where(QueryableValueMoreThan(5)).Count());
}

// Fine for in-memory linq
private Func<Item, bool> ValueMoreThan(int value)
{
return i => i.Value > value;
}

// Also fine for database query translation
private Expression<Func<Item, bool>> QueryableValueMoreThan(int value)
{
return i => i.Value > value;
}

private static IEnumerable<Item> GetItems2(IRepository repo)
{
return repo.GetItems2().SelectMany(i => repo.GetOtherItems2(i.Id, 0));
}

private static IEnumerable<Item> GetItems1(IRepository repo)
{
return repo.GetItems1().SelectMany(i => repo.GetOtherItems1(0, i.Id));
}

private static IRepository SetupRepo()
{
var repo = MockRepository.GenerateMock<IRepository>();
repo.Stub(r => r.GetItems1()).Return(new[] { new Item { Id = 1, Value = 3 } });
repo.Stub(
r => r.GetOtherItems1(0, 1)).Return(new[] { new Item { Id = 2, Value = 3 },
new  Item { Id = 3, Value = 6 } });
repo.Stub(r => r.GetItems2()).Return(new[] { new Item { Id = 4, Value = 3 } });
repo.Stub(
r => r.GetOtherItems2(4, 0)).Return(new[] { new Item { Id = 5, Value = 6 },
new Item { Id = 6, Value = 7 } });
return repo;
}

public interface IRepository
{
IEnumerable<Item> GetItems1();
IEnumerable<Item> GetOtherItems1(int foo, int id);
IEnumerable<Item> GetItems2();
IEnumerable<Item> GetOtherItems2(int id, int bar);
}

public class Item
{
public int Id { get; set; }
public int Value { get; set; }
}

• Welcome to the Code Review, which is part of the Stack Exchange network. A network wide convention is not to add greetings or footers in your posts. Please refrain from doing so in the future. Thanks. – Steven Jeuris Dec 13 '11 at 13:39

Create a class that holds your parameters and instead of passing individual parameters, pass in the class object. something like:

class MyClass
{

public MyClass(){}

public int ItemId { get; set;}
public string ItemParam1 {get; set;}
....
}

• This could be made cleaner by using auto properties. – WestDiscGolf Dec 12 '11 at 11:22