The C# compiler doesn't do much at all - it just calls the methods you tell it to, basically.
You could argue that removing unnecessary Select calls is an optimization:
from x in collection
where x.Condition
select x
is compiled to collection.Where(x => x.Condition)
instead of collection.Where(x => x.Condition).Select(x => x)
as the compiler recognises the identity transformation as being redundant. (A degenerate query of the form from x in collection select x
is immune to this optimization, however, to allow LINQ providers to make sure that any query goes through at least one of their methods.)
The LINQ to Objects Min
method just does a foreach, yes. Various LINQ to Objects methods do perform optimization. For example, Count()
will check whether the data source implements ICollection
or ICollection<T>
and use the Count
property if so. As madgnome points out in a comment, I wrote a bit more about this in a blog post a while ago.
Of course, other LINQ providers can perform their own optimizations.