ca9163d9
ca9163d9

Reputation: 29159

Yield return IEnumerable<IEnumerable<...>>

The following code creates an intermediate instance of List<string> and append values to it before yield return it. Is there a good way to avoid creating the instance and yield return the cell values directly?

IEnumerable<IEnumerable<string>> GetStrValues()
{
    ......
        foreach (var r in rows)
        {
            var row = new List<string>();
            foreach (var c in r.Cells())
            {
                var value = getCellStr(c);
                row.Add(value);
            }
            yield return row;
        }
    }
}

Upvotes: 2

Views: 1355

Answers (2)

vgru
vgru

Reputation: 51204

To avoid creating the list, you can use LINQ:

IEnumerable<IEnumerable<string>> GetStrValues()
{
     return rows.Select(r => r.Cells().Select(getCellStr));
}

This will execute lazily, i.e. no intermediate list will be created. It's a neat way to avoid allocating memory you won't be needing (unless you are going to iterate several times over the inner IEnumerable<string>, and getCellStr is expensive).

Upvotes: 7

Scott Chamberlain
Scott Chamberlain

Reputation: 127543

You can get deffered action per cell by using two functions.

IEnumerable<IEnumerable<string>> GetStrValues()
{
    ......
        foreach (var r in rows)
        {
            yield return GetCellValues(row);
        }
    }
}

IEnumerable<string> GetCellValues(Row r)
{
    foreach (var c in r.Cells())
    {
        yield return getCellStr(c);
    }  
}

Upvotes: 4

Related Questions