开发者

What are the mechanics of the expression tree limitation here?

开发者 https://www.devze.com 2023-04-10 18:35 出处:网络
The fact that I expected this to work and it didn\'t leads me to search for the piece of the picture that I don\'开发者_如何学Got see.

The fact that I expected this to work and it didn't leads me to search for the piece of the picture that I don'开发者_如何学Got see.

What are the mechanics of the expression tree limitation here?


Imagine that query being remoted over to a database. How is the database engine supposed to reach over the internet as it is executing the query and tell the "count" variable on your machine to update itself? There is no standard mechanism for doing so, and therefore anything that would mutate a variable on the local machine cannot be put into an expression tree that would run on a remote machine.

More generally, queries that cause side effects when they are executed are very, very bad queries. Never, ever put a side effect in a query, even in the cases where doing so is legal. It can be very confusing. Remember, a query is not a for loop. A query results in an object represents the query, not the results of the query. A query which has side effects when executed will execute those side effects twice when asked for its results twice, and execute them zero times when asked for the results zero times. A query where the first part mutates a variable will mutate that variable before the second clause executes, not during the execution of the second clause. As a result, many query clauses give totally bizarre results when they depend on side effect execution.

For more thoughts on this, see Bill Wagner's MSDN article on the subject:

http://msdn.microsoft.com/en-us/vcsharp/hh264182

If you were writing a LINQ-to-Objects query you could do what you want by zipping:

var zipped = model.DirectTrackCampaigns.Top("10").Zip(Enumerable.Range(0, 10000), (first, second)=>new { first, second });

var res = zipped.Select(c=> new Campaign { IsSelected = c.second % 2 == 0, Name = c.first.CampaignName };

That is, make a sequence of pairs of numbers and campaigns, then manipulate the pairs.

How you'd do that in LINQ-to-whatever-you're-using, I don't know.


When you pass anything to a method that expects an Expression, nothing is actually evaluated at that time. All it does is, it breaks apart the code and creates an Expression tree out of it.

Now, in .Net 4.0, alot of things were added to the Expression API (including Expression.Increment and Expression.Assign which would actually be what you're doing), however the compiler (I think it's a limitation of the C# compiler) hasn't been updated yet to take advantage of the new 4.0 Expression stuff. Therefore, we're limited to method calls, and assignment calls will not work. Hypothetically, this could be supported in the future.


IsSelected = (count++) % 2 == 0

Pretty much means:

IsSelected = (count = count + 1) % 2 == 0

That's where the assignment is happening and the source of the error.

According to the different answers to this question, this should be possible with .NET 4.0 using expressions, though not in lambdas.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号