
Originally Posted by
m^2
Yes, I was unclear. The reason why lambda expressions are lazy is the LINQ guys wanted lazy evaluation. Querying database is slow and if laziness allows them to avoid it, it's well worth having a slightly higher overhead.
I think, you're confusing lambda and LINQ. Lambda functions are not lazy evaluated. They are simply delegates (or anonymous functions). You can even invoke a lambda function asynchronously. But, these are irrelevant to lazy evaluation. For LINQ case, lazy evaluation is "must-have". Because, you can add queries on queries. So, at data reading, they have to be evaluated to simplify LINQ queries to actual data queries (say SQL). To make it clear, here is "real" product "LINQ to SQL" code from our applications:
Code:
private static IQueryable<UdtProject> BuildQuery(ModuleDataContext context,
int companyID, int engineerID, int cityID, int countyID, string approvalState)
{
var query = from x in context.UdtProjects select x;
if (companyID > 0)
query = from x in query where x.CompanyID == companyID select x;
if (engineerID > 0)
query = from x in query where x.EngineerID == engineerID select x;
if ((cityID > 0) && (countyID < 0))
query = from x in query where x.County.CityID == cityID select x;
if (countyID > 0)
query = from x in query where x.CountyID == countyID select x;
if (!String.IsNullOrEmpty(approvalState))
{
UdtProjectApprovalState state = ObjectParser.ParseEnum<UdtProjectApprovalState>(approvalState);
query = from x in query where x.ApprovalState == state.ToString() select x;
}
return query;
}
This code does not execute any single line of SQL code. It accumulates LINQ queries over and over again by given filtering parameters. If you want to fetch data you can just simply call "query.ToArray()" to compile LINQ query into SQL on demand. As to overhead, it's very little today with service packs. At first times, it was damn slow comparing to precompiled queries.
Here is the code that calls the above code. Note that until "ToArray()", it's still not evaluated.
Code:
...
using (ModuleDataContext context = new ModuleDataContext(CmsHelper.ConnectionString))
{
var query = BuildQuery(context, companyID, engineerID, cityID, countyID, approvalState);
return (from x in query
orderby x.CreationTime descending,
x.ReviewTime descending,
x.ApprovalTime descending
select x).ToArray();
}
...

Originally Posted by
m^2
...One concrete example is the already mentioned laziness suddenly appearing in a tiny subset of the language. Another is that equals() compares objects of particular classes not by contents but by references. The objects that I'm aware of (maybe there are others too, I won't know unless I ever get a bug with them) are collections...
"Equals()" are used for reference equality by default. In intellisense tip, description is clear to me. It compares references not actual data. If you want to compare containing data, there is a IEquatable interface for such usages (you have to implement that interface for your objects). If you want to extend this "comparing containing data" feature to all objects, you can still write a simple extension method which invokes reflection to compare arbitrary classes' containing data.
I think, you make some assumption before using a method and that causes to pull you into trouble. Fastest way could be just read intellisense tip.