andriej
andriej

Reputation: 2266

How to pass a subset of a collection to a C# method?

In C++, anytime I want to process some range of items I do something like this:

template<class Iterator>
void method(Iterator range_begin, Iterator range_end);

Is there such a convenient way to do this in C#, not only for System.Array but for other collection classes as well?

Upvotes: 6

Views: 2556

Answers (6)

Vlad
Vlad

Reputation: 35594

I can't think of any at the moment, but using LINQ you can easily create an IEnumerable<T> representing a part of your collection.

As I understand it, the C# way is to see a part of a collection as a collection itself, and make your method to work on this sequence. This idea allows the method to be ignorant to whether it's working on the whole collection or its part.

Examples:

void method(IEnumerable<T> collection)
{ ... }

// from 2-nd to 5-th item:
method(original.Skip(1).Take(4));
// all even items:
method(original.Where(x => x % 2 == 0));
// everything till the first 0
method(original.TakeWhile(x => x != 0));
// everything
method(original);

etc.

Compare this to C++:

// from 2-nd to 5-th item:
method(original.begin() + 1, original.begin() + 5);
// everything
method(original.begin(), original.end());
// other two cannot be coded in this style in C++

In C++, your code calculates iterators in order to pass them around, and mark the beginning and the end of your sequence. In C#, you pass lightweight IEnumerables around. Due to the lazy evaluation this should have no overhead.

Upvotes: 5

James Johnson
James Johnson

Reputation: 46067

It depends on what kind of collection you're using. Some have more capabilities than others. Using a list, you can do something like this:

List<string> lst = new List<string>();
lst = lst.Where(str => str == "Harry" || str == "John" || str == "Joey").ToList();

Upvotes: 0

Matthew Whited
Matthew Whited

Reputation: 22443

Could you just use IEnumerable<> and pass in your values as a LINQ query?

void MyMethod<T>(IEnumerable<T> workSet) {
    foreach (var workItem in workSet) {
        doWorkWithItem(workItem);
    }
}

var dataset = yourArray.SkipWhile(i=>i!=startItem).TakeWhile(i=>i!=endItem);
MyMethod(dataset);

var pagedSet = yourArray.Skip(pageSize * pageNumber).Take(pageSize);
MyMethod(pagedSet);

Upvotes: 1

balexandre
balexandre

Reputation: 75103

wouldn't that be the same as using LAMBDA expression to subset your list?

public myClass {
    public int Year { get; set; }
    ...
}

then...

List<myClass> allClasses = db.GetClasses();
IEnumerable<myClass> subsetClasses = allClasses.where(x => x.Year >= 1990 && x.Year <= 2000);

processSubset(subsetClasses);

or you could use skip() and take() just like in a database if you want to process n items in the collection without a given argument.

Upvotes: 0

Ed Swangren
Ed Swangren

Reputation: 124722

// ...
using System.Linq;

IEnumerable<T> GetSubset<T>( IEnumerable<T> collection, int start, int len )
{
    // error checking if desired
    return collection.Skip( start ).Take( len );
}

Upvotes: 8

leppie
leppie

Reputation: 117280

If you use LINQ, take a look at Skip and Take.

Upvotes: 4

Related Questions