0

As input i have object that implements IDataRecord(row of some abstract table), so it have indexer, and by giving it some integer i can retrive object of some type. As output my code must get some range of cells in that row as array of given type objects.

So I've written this method(yes, i know, it can be easly converted to extension method, but i don't need this, and also i don't really want to have this method visible outside of my class):

private static T[] GetRange<T>(IDataRecord row, int start, int length)
{
    var result = new List<T>();          

    for (int i = start; i < (start + length); i++)
    {
        result.Add((T)row[i]);
    }

    return result.ToArray();
}

It works fine, but this method logic seems like something very common. So, is there any method that can give same(or almost same) result in .NET Framework FCL/BCL?

rufanov
  • 3,266
  • 1
  • 23
  • 41
  • Does IDataRecord implement IEnumerable? – Yogesh Aug 22 '14 at 04:36
  • @Yogesh, No, [IDataRecord Interface](http://msdn.microsoft.com/en-us/library/system.data.idatarecord(v=vs.110).aspx) don't implement IEnumerable. – rufanov Aug 22 '14 at 05:01
  • Then the answer is no I guess. You could have used linq to get the result you wanted, but since IDataRecord doesn't implement IEnumerable, your above posted code is the best bet. – Yogesh Aug 22 '14 at 05:03

4 Answers4

1

Use Skip and Take.

var rangeList = result.Skip(start - 1).Take(length);
Haojie
  • 5,665
  • 1
  • 15
  • 14
  • Unfortunately Skip and Take don't work with just any object with indexer(like mine "row" parameter). It's require that object should implement IEnumerable interface. – rufanov Aug 22 '14 at 04:58
1

No, it is not in the BCL.

You should however not create a List<> first and then copy that to the array. Either return the List<> itself (and construct it with the appropriate initial capacity), or create the array immediately like this:

private static T[] GetRange<T>(IDataRecord row, int start, int length)
{
    var result = new T[length];

    for (int i = 0; i < length; i++)
    {
        result[i] = (T)row[start + i];
    }

    return result;
}

Here is an alternative (for all you LINQ lovers):

// NB! Lazy enumeration
private static IEnumerable<T> GetRange<T>(IDataRecord row, int start, int length)
{
    return Enumerable.Range(start, length).Select(i => (T)row[i]);
}

We repeat here what was stated in the comments to the question: The interface System.Data.IDataRecord (in System.Data.dll assembly) does not inherit IEnumerable<> or IEnumerable.

Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
0

If you want to 'TakeARange' you should have a collection as input parameter. Here you don't have one.

You just have a IDataRecord (eg. a single row) that has an indexer. You should expose a property called Cells that return the list you work with in the indexer implementation.

Your method should look like this:

private static T[] TakeRange<T>(IEnumerable cells, int start, int length)
{
    return cells.Skip(start - 1).Take(length)
}
Mauro Sampietro
  • 2,739
  • 1
  • 24
  • 50
  • As i said in original question - i DON'T have control on input. And i don't want to "get some range from object that implents IEnumerable" - i want to get some range from object that have indexer. I'm exactly want to find standard methods of this, not to do something totally else. If there is no such method, then it's fine. – rufanov Aug 23 '14 at 04:00
0

Well.. Seem's like there is no such method in FCL/BCL

rufanov
  • 3,266
  • 1
  • 23
  • 41