Hello. There are two methods, differing only in one line. I would very much like to combine them into one, but I just can’t figure out how to do it.

public long FindPosition(Predicate<T> match) { if(match == null) throw new ArgumentNullException("match"); long position = FirstItemPosition; while(position != End) { Item<T> item = GetItemAtPosition(position); if(match(item.Value)) return position; position = item.Next; } return position; } private long FindPosition(Predicate<Item<T>> match) { if(match == null) throw new ArgumentNullException("match"); long position = FirstItemPosition; while(position != End) { Item<T> item = GetItemAtPosition(position); if(match(item)) return position; position = item.Next; } return position; } 

    2 answers 2

    • There is no need to perform the Extract Method , and no need to make a template class. You just need to throw out the first of the FindPosition overloads:

    The second overload (which takes Predicate<Item<T>> ) has an obvious semantics - it returns the first Item<T> that satisfies the predicate. If there are none, it returns End .

    • The need for the first overload personally seems to me extremely doubtful. Instead of writing an additional method, it is easier to write the equivalent predicate Predicate<Item<T>> , which will perform some actions with item.Value - you can always do this:

       Predicate<Item<T>> predicate = item => item.Value > 0; 
    • As a reasonable alternative, consider using FirstOrDefault to your sequence, so as not to reinvent the wheel once again .

    Put it Item<T> GetItemAtPosition(position) you can do this by turning your Item<T> GetItemAtPosition(position) method into an IEnumerable<Item<T>> .


    • If it so happens that FindPosition(Predicate<T> match) cannot be thrown out, and you do not plan to use LINQ , then perform the inverse transformation:

       public long FindPosition(Predicate<T> match) { return FindPosition(item => match(item.Value)); } private long FindPosition(Predicate<Item<T>> match) { ... } 
    • The need for the first overload is that the Item structure can only be used inside an assembly. The external code knows nothing about this structure, only the Value field is returned to it. - Veikedo
    • @Veikedo Such restrictions are usually well reflected in the text of the question. Updated the answer. - Costantino Rupert
    • @ Kotik_khohet_kusat, yes, it was just :) Thank you very much for your help. Ps. FirstOrDefault here, by the way, cannot be used because the position is returned in the Stream stream, where this Item is recorded, and not the Item itself - Veikedo
    • @Veikedo Well, you see, you concealed from us one more important detail from the statement of the problem :) - Costantino Rupert
    • @ Kotik_hochet_kusat, it seemed to me that this detail from the method signature can be seen :). In any case, thanks again - Veikedo

    I think you can use the template class:

     public class MyClass<T> { public long FindPosition(Predicate<T> match) { return 0; } } 

    Using:

     MyClass<int> obj = new MyClass<int>(); MyClass<List<int>> obj2 = new MyClass<List<int>>();