2

My code has something like this:

HttpFileCollection files

Instead of looping through each file and adding up the file.ContentLength to get the total length of all content e.g.

        int totalLength = 0;
        for (int i = 0; i < files.Count; i++)
        {
            totalLength += files[i].ContentLength;
        }

Is there a way I can do this with a lambda expression so I have something like..

int totalLength = files.[some sort of delegate here to do the addition].

Thanks in advance.

Edit: HttpFileCollection has a GetEnumeratorMethod but would it need to implement IEnumerable to use a lambda expression?

Remotec
  • 10,304
  • 25
  • 105
  • 147

2 Answers2

6

You could use LINQ:

int totalLength = files.AllKeys.Select(k => files[k]).Sum(f => f.ContentLength);

Unfortunately, HttpFileCollection's enumerator returns an enumeration of strings. In order to get the actual objects (HttpPostedFile), you need to access the "dictionary" by key. This converts the enumerator to an enumeration of HttpPostedFile instances (via Select), then sums the content length.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • Hi just to understand, why dont I need to iterate through the files and cast? Is there some sort of automatic enumeration taking place on the collection. Not quite got to grips with this despite reading "C# In Depth" :) – Remotec Mar 04 '10 at 16:46
  • HttpFileCollection implements IEnumerable, so you can enumerate it as "object"s. The above LINQ statement does the cast inline, and then handles the sum for you. It's, internally, basically the same as doing a foreach, casting to HttpPostedFile, then summing ContentLength (but much easier to read and write). – Reed Copsey Mar 04 '10 at 16:53
  • mmm - that shouldn't happen, given the code you posted above... Are you sure "files" is an HttpFileCollection, and not a collection of strings, somehow? – Reed Copsey Mar 04 '10 at 16:57
  • Sorry deleted my comment just before u replied as it wasnt relevant. The code is correct but somehow a string is getting into the file collection from the Request.Files object. (For reference my comment mentioned an invalid cast exception). – Remotec Mar 04 '10 at 16:59
  • I actually figured it out - my updated answer will work correctly. – Reed Copsey Mar 04 '10 at 17:00
  • What a wacky collection. :-) – Samuel Neff Mar 04 '10 at 17:11
  • You know, that "Select" is wholly unnecessary. files.AllKeys.Sum(x => files[x].ContentLength) works fine. – Protector one Apr 28 '10 at 08:33
1

To add to the accepted answer, indeed, you can use this:

int totalLength = files.AllKeys.Select(k => files[k]).Sum(f => f.ContentLength);

The reason why you don't have to enumerate in your code is because the Sum extension method does that for you. If you run it through Reflector you eventually find this bit of code:

public static int Sum(this IEnumerable<int> source)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    int num = 0;
    foreach (int num2 in source)
    {
        num += num2;
    }
    return num;
}

As you see ,it's not really rocketscience. It's almost the same as your original code even!

Note: If you want to find this code, crack open System.Core, go to the System.Linq namespace and open the Enumerable class definition. You'll find these methods here (among other places I think).

Erik van Brakel
  • 23,220
  • 2
  • 52
  • 66