0

I've got a List of entities called usages, from which I create an IEnumerable of entities of type AdminUsage, as follows:

var models = usages.Select(u => new AdminUsage(u));

when I call .ToList() on models I get an IndexOutOfRange exception with the message "Index was outside the bounds of the array."

Why could this be happening, and how can I successfully get a List of type AdminUsage from my original list usages?

Edit: Ok, so actually the index that was out of range was inside the AdminUsage constructor:

public AdminUsageModel(Usage usageDetails) { Title = usageDetails.UsageName[0] }

So my revised question is why is the exception only thrown on the call .ToList() and not on the original .Select()?

Alex
  • 136
  • 1
  • 8
  • 1
    Are you modifying `usages` while calling `ToList` from another part of your code? – Yuval Itzchakov Feb 25 '15 at 15:45
  • 2
    Can you post the code of the `AdminUsage` constructor you're calling? – Frédéric Hamidi Feb 25 '15 at 15:45
  • Can we also see the code in the constructor for AdminUsage() – David Watts Feb 25 '15 at 15:45
  • My first guess is *You're modifying the `usages` in another thread* – Sriram Sakthivel Feb 25 '15 at 15:46
  • You need to provide a minimal example that reproduces the problem. We can only guess at what you might be doing to cause this problem, there are many possibilities. – Servy Feb 25 '15 at 15:52
  • 1
    Oh my gosh, @FrédéricHamidi - I went to post the code and immediately noticed that inside the constructor I am taking the first character of a string without checking the length of the string first. Doh! Mystery solved. Feel like an idiot for not noticing that before! But why does it throw this error only on the call .ToList() – Alex Feb 25 '15 at 15:53
  • Because only at that point IEnumerable is iterated over and u=> new AdminUsage(u) is called for each item (usage) – milanio Feb 25 '15 at 16:00

1 Answers1

3

why is the exception only thrown on the call .ToList() and not on the original .Select()?

Because a Select() doesn't do anything, it's a promise. With ToList() you materialize that promise, so that's when the code is actually executed, and the exception thrown.

See also MSDN: IEnumerable<T>.Select():

This method is implemented by using deferred execution. The immediate return value is an object that stores all the information that is required to perform the action. The query represented by this method is not executed until the object is enumerated either by calling its GetEnumerator method directly or by using foreach in Visual C# or For Each in Visual Basic.

See also Deferred execution and eager evaluation, Trying to understand how linq/deferred execution works.

Community
  • 1
  • 1
CodeCaster
  • 147,647
  • 23
  • 218
  • 272
  • Feel free to close as dupe with a canonical question explaining deferred execution, I couldn't find one. – CodeCaster Feb 25 '15 at 16:07
  • "Promise" is actually a good analogy (for those who do not understand what deferred execution" means. – helb Feb 25 '15 at 16:07
  • @helb it's not a [promise in the sense commonly used](http://en.wikipedia.org/wiki/Futures_and_promises), "deferred execution" is the keyword here. – CodeCaster Feb 25 '15 at 16:09
  • 1
    it just came to my mind and I revised my comment. I find "Promise" still helpful for explanatory purose ;-) – helb Feb 25 '15 at 16:13