1

I have a lambda expression:

(x) => x.Visits++

At runtime, I want to translate this into the string:

"set Visits = Visits + 1"

or, potentially, if the underlying data store is different (like MongoDB)

{$inc: {Visits : 1}}

I think the way to do this is to use expression trees, but when I assign the lambda expression to an expression tree, I get "An expression tree may not contain an assignment operator".

Is there any way to accomplish this short of writing a full up linq implementation that supports Update?

5
  • Would this help Lambda to Expression tree conversion? Commented Jan 9, 2012 at 22:31
  • @oleksii not in this case, no. Without the Expression<...> it will compile (as a delegate); with the Expression<...> it won't. Commented Jan 9, 2012 at 22:50
  • Would something like this help (for linqpad)? int i = 0; Func<int, int> inc = x => ++x; Func<int, int> dec = x => --x; Expression<Func<int, int>> f = x => inc(dec(inc(x))); while(i < 10) { i = f.Compile()(i); i.Dump(); } f.Dump(); Commented Jan 9, 2012 at 23:32
  • CrazyDart - I started down that road a bit by defining extension methods for "allowed operations". You are right that it moves the ball down the road a bit - at least now the compiler generates an expression. It is not as elegant but may be a good compromise for now. Commented Jan 10, 2012 at 0:14
  • Alas, CrazyDart - expressions with statement bodies are not supported either. Your suggestion gets too unwieldy for complex queries. Thanks for the idea, though. Commented Jan 10, 2012 at 0:22

2 Answers 2

4

That simply isn't supported by the current C# compiler, and I haven't heard about any changes in vNext. Of course, strictly speaking it isn't defined for C# 3 / 4 - there is just a "is defined elsewhere" (actually, AFAIK: the spec for handling expression tree construction still isn't formally documented; this could be a positive thing, as it is hard to argue that it will require specification changes ;p).

The funny thing is: from .NET 4.0 onwards, the expression tree API does support mutate (in this case, see Expression.Increment and Expression.PostIncrementAssign) - so you could create the expression tree at runtime via Expression.* code, but frankly that is a pain and hard to manage. So there is potential for this to change, but don't be too hopeful.

Also keep in mind - the expression tree analysis to pull it back out again is far from trivial. Doable, sure; easy: no.

Sign up to request clarification or add additional context in comments.

4 Comments

Yeah, we never did ship that spec, sorry. Regarding the expression tree API: we considered it, along with considering supporting conversions from statement lambdas to expression trees. The thing is, we do not have a compelling end-user scenario that is so great that it would cause us to cancel or delay more interesting work (like dynamic, or async). It would be nice to fill in those holes, but "nice" is insufficiently compelling.
Good to know, tnx Mark and Eric.
Thanks Marc - agreed, the second step is non-trivial, but certainly not harder than implementing a linq provider. I simply wanted something lighter weight than Linq to hide that complexity from the end users of my API and provide them with query format that was agnostic to the underlying storage provider. It looked so elegant that I was SURE it would work! Oh well.
@Eric keep shipping other awesome stuff and I'll forgive you :p agree that this spec has a tiny audience - writing new tools is better. Finding an awesome example for the statement scenario is also elusive, agreed.
0

There is no need in the compiler support, the expression tree can be constructed from MSIL. This project implements it - https://github.com/kostat/XLinq

Disclaimer: I'm a maintainer.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.