I have a base class which needs to process the names of the properties of derived classes (explicit access). To do so, I created a method which takes a lambda expression as input:
private string GetMemberName(Expression<Func<object>> expression)
{
//gets the property name (MemberExpression or UnaryExpression)
//out of scope
return propertyName;
}
This allows me to call the method like so:
derived.GetMemberName(() => derived.MyPropertyInt);
derived.GetMemberName(() => derived.MyPropertyStr);
The problem is that object is not restrictive at all. I can also call:
derived.GetMemberName(() => "something"); //does not "return" anything but compiles (out of scope)
derived.GetMemberName(() => anotherClass.RandomMember); //not derived from "base"
How can I restrict the GetMemberName method so that it can only accept as input the members of the classes which derive from my base class? Setting GetMemberName(Expression<Func<MyBaseClass>> expression) restricts access to an entire class. Setting GetMemberName(Expression<Func<MyBaseClass, object>> expression) restricts access to the current instance but still allows "random" objects to be passed.
EDIT:
The comment for derived.GetMemberName(() => "something"); was in the context of returning the property name, not the "value" of the lambda expression. The GetPropertyName method does not return anything, due to the fact that I'm only analyzing MemberExpression or UnaryExpression.
How can I restrict the GetMemberName method so that it can accept only members of the classes which derive from my base class?
It's not clear what you mean by "accept" here, but if you're trying to restrict the set of valid lambda expressions to ones which uses members of your class, you can't. Lambda expressions and expression trees happen to be useful for getting this information, but that's not what they're designed for, so there are no specific features accommodating this. You'll always be able to use a lambda expression which doesn't just use a property.
The simplest approach is probably just to check this at execution time. You won't be able to stop people abusing your method at compile-time, but so long as it's simple to do the right thing, I wouldn't worry too much about callers doing the wrong thing - just make the error message really clear.
Related
When constructing an expression tree, I have to use nodes invoking external methods in order to obtain values the expression could then continue evaluation with.
These methods are supplied as Func<T> and my code has no knowledge of where they originate from.
What is the most correct way of performing the mentioned invocation? I've tried something like this:
private Dictionary<string, Delegate> _externalSymbols;
private Expression _forExternalSymbol(string identifier)
{
Delegate method = _externalSymbols[identifier];
return Expression.Call(method.Method);
}
which works as long as the method fetched from the dictionary was created in compile-time. However, in case of Func<T> being a dynamic method obtained, for instance, by compiling another expression in runtime, this won't work out throwing
ArgumentException: Incorrect number of arguments supplied for call to method 'Int32 lambda_method(System.Runtime.CompilerServices.ExecutionScope)'
The desired effect may be achieved by wrapping the given function into one extra expression, but that seems quite hideous comparing to what it used to look like:
private Expression _forExternalSymbol(string identifier)
{
Delegate method = _externalSymbols[identifier];
Expression mediator = method is Func<double> ?
(Expression)(Expression<Func<double>>)(() => ((Func<double>)method)()) :
(Expression<Func<string>>)(() => ((Func<string>)method)());
return Expression.Invoke(mediator);
}
Also, this is hardly an extensible approach should I need to add support for types other than double and string.
I would like to know if there are better options which would work with dynamically created methods (preferably applicable to .NET 3.5).
which works as long as the method fetched from the dictionary was created in compile-time
No, it works as long as the method is static. For example, it also won't work if the delegate is a lambda that references something from its parent score (i.e. it's a closure).
The correct way to invoke a delegate is to use Expression.Invoke(). To get an Expression that represents your delegate, use Expression.Constant():
Expression.Invoke(Expression.Constant(method)))
I want to be able to call properties on objects that might be null but not explicitly have to check whether they are null or not when calling.
Like this:
var something = someObjectThatMightBeNull.Property;
My idea is to create a method that takes an Expression, something like this:
var something = GetValueSafe(() => someObjectThatMightBeNull.Property);
TResult? GetValueSafe<TResult>(Expression<Func<TResult>> expression)
where TResult : struct
{
// what must I do?
}
What I need to do is to inspect the expression and determine if someObjectThatMightBeNull is null or not. How would I do this?
If there is any smarter way of being lazy I'd appreciate that too.
Thanks!
It's complicated, but it can be done, without leaving "expression-land":
// Get the initial property expression from the left
// side of the initial lambda. (someObjectThatMightBeNull.Property)
var propertyCall = (MemberExpression)expression.Body;
// Next, remove the property, by calling the Expression
// property from the MemberExpression (someObjectThatMightBeNull)
var initialObjectExpression = propertyCall.Expression;
// Next, create a null constant expression, which will
// be used to compare against the initialObjectExpression (null)
var nullExpression = Expression.Constant(null, initialObjectExpression.Type);
// Next, create an expression comparing the two:
// (someObjectThatMightBeNull == null)
var equalityCheck = Expression.Equal(initialObjectExpression, nullExpression);
// Next, create a lambda expression, so the equalityCheck
// can actually be called ( () => someObjectThatMightBeNull == null )
var newLambda = Expression.Lambda<Func<bool>>(equalityCheck, null);
// Compile the expression.
var function = newLambda.Compile();
// Run the compiled delegate.
var isNull = function();
That being said, as Andras Zoltan has so eloquently put in the comments: "Just because you can doesn't mean you should." Make sure you have a good reason to do this. If there's a better way to, then do that instead. Andras has a great workaround.
What you're talking about is called null-safe dereferencing - this SO specifically asks that question: C# if-null-then-null expression.
Expressions aren't really the answer (see below for clarification of my reasons for that statement). This extension method might be, though:
public static TResult? GetValueSafe<TInstance, TResult>(this TInstance instance,
Func<TInstance, TResult> accessor)
where TInstance : class
where TResult : struct
{
return instance != null ? (TResult?)accessor(instance) : (TResult?)null;
}
And now you can do:
MyObject o = null;
int? i = o.GetValueSafe(obj => obj.SomeIntProperty);
Assert.IsNull(i);
Obviously this is most useful when the property is a struct; you can reduce to any type and just use default(TResult) - but then you'd get 0 for ints, doubles etc:
public static TResult GetValueSafe<TInstance, TResult>(this TInstance instance,
Func<TInstance, TResult> accessor, TResult def = default(TResult))
where TInstance : class
{
return instance != null ? accessor(instance) : def;
}
This second version is more useful specifically because it works for any TResult. I've extended with an optional parameter to allow the caller to provide the default, e.g (using o from previous code):
int i = o.GetValueSafe(obj => obj.SomeIntProperty); //yields 0
i = o.GetValueSafe(obj => obj.SomeIntProperty, -1); //yields -1
//while this yields string.Empty instead of null
string s = o.GetValueSafe(obj => obj.SomeStringProperty, string.Empty);
Edit - in response to David's comment
David suggested my answer is wrong because it doesn't provide an expression-based solution, and that is what was asked for. My point is that any truly correct, and indeed responsible, answer on SO should always try to seek a simpler solution for the person asking the question if one exists. I believe it is widely accepted that over-complicated solutions to otherwise simple problems should be avoided in our day-to-day professional lives; and SO is only as popular as it is because it's community behaves in the same way.
David also took issue with my unjustified statement that 'they're not the solution' - so I'm going to expand upon that now and show why the expression-based solution is largely pointless, except in a rare edge-case that the OP doesn't actually ask for (which, incidentally, David's answer doesn't cover either).
The irony being that it makes this answer in itself perhaps unnecessarily complicated :) You can safely ignore from here down if you don't actually care why expressions aren't the best route
Whilst it is correct to say that you can solve this with expressions, for the examples laid out in the question there is simply no reason to use them - it's over-complicating what is ultimately quite a simple issue; and at runtime the overhead of compiling the expression (and subsequently throwing it away, unless you put caching in, which is going to be tricky to get right unless you emit something like call sites, like the DLR uses) is huge compared to the solution I present here.
Ultimately the motivation of any solution is to try and keep the work required by the caller to a minimum, but at the same time you also need to keep the work that is to be done by the expression analyzer to a minimum as well, otherwise the solution becomes almost unsolvable without a lot of work. To illustrate my point - let's look at the simplest we can achieve with a static method that takes an expression, given our object o:
var i = GetValueSafe(obj => obj.SomeIntProperty);
Uh-oh, that expression doesn't actually do anything - because it's not passing the o to it - the expression itself is useless to us, because we need the actual reference to o that could be null. So - the first of the solutions to this, naturally, is to explicitly pass the reference:
var i = GetValueSafe(o, obj => obj.SomeIntProperty);
(Note - could also be written as an extension method)
Thus the static method's job is to take the first parameter and pass it to the compiled expression when it invokes it. This also helps with identifying the type of the expression whose property is sought. It also, however, completely nullifies the reason to use an expression in the first place; since the method itself can immediately make the decision to access the property or not - since it has a reference to the object that could be null. Thus, in this case, it's easier, simpler and faster to simply pass a reference and accessor delegate (instead of an expression), as my extension method does.
As I mentioned, there is a way to get around having to pass the instance and that is to do one of the following:
var i = GetValueSafe(obj => o.SomeIntProperty);
Or
var i = GetValueSafe(() => o.SomeIntProperty);
We're discounting the extension method version - because with that we get a reference passed to the method, and as soon as we get a reference we can do away with expressions, as my last point proved.
Here we're relying on the caller to understand that they must include an expression that represents the actual instance (be it an in-scope property or field or local variable) in the body of the expression, on the left hand side of the member read, so that we can actually get a concrete value from it in order to do the null-check.
This is not a natural use of expression parameters, first of all, so I believe your callers could be confused. There's also another issue, which I think will be a killer if you intend to use this a lot - you cannot cache these expressions, because each time the instance, whose 'null-ness' you want to sidestep, is being baked into the expression that is passed. This means that you are always having to recompile the expression for every call; and that is going to be really slow. If you parameterise the instance in the expression you can then cache it - but then you end up with our first solution which required the instance to be passed; and again I've already shown there that we can then just use a delegate!
It is relatively easy - using the ExpressionVisitor class - to write something that can turn all property/field reads (and method calls for that matter) into 'safe' calls like you want. However, I cannot see any benefit to doing this unless you intend to do a safe read on something like this: a.b.c.d. But then the augmentation of value types to nullable versions of themselves is going to cause you a good few headaches in the expression-tree rewriting I can tell you; leaving a solution that hardly anyone will understand :)
This seems odd to me, but I remember a thread where Eric Lippert commented on the inability (by design, or at least convention, I think) of C# to overload methods based on return type, so perhaps it's in some convoluted way related to that.
Is there any reason this does not work:
public static T Test<T>() where T : new()
{
return new T();
}
// Elsewhere
SomeObject myObj = Test();
But this does:
var myObj = Test<SomeObject>();
From a certain perspective, they're both fine, in that you're not Repeating Yourself (in a very small way), but is this just a different pass of the compiler?
First off, this is "overloading based on return type":
void M(int x){...}
int M(int x){...}
string M(int x){...}
The declarations are not legal; you can't overload a method based on return type because the return type is not part of the signature, and the signature has to be unique.
What you are talking about is method type inference based on the method's return type. We don't support that either.
The reason is because the return type might be what you are trying to figure out.
M(Test());
What's the return type of Test? That depends on which overload of M we choose. What overload of M do we choose? That depends on the return type of Test.
In general, C# is designed so that every subexpression has a type, and the types are worked out from the "inside" towards the "outside", not from the outside to the inside.
The notable exceptions are anonymous functions, method groups, and null:
M(x=>x+1)
What's the type of x=>x+1? It depends on which overload of M is called.
M(N); // N is a method group
what's the type of N? Again, it depends on which overload of M is called.
And so on. In these cases we do reason from "outside" to "inside".
Type inference involving lambdas is extremely complicated and was difficult to implement. We don't want to have that same complication and difficulty throughout the compiler.
Except for typeless expressions (null, method groups, and lambda expressions), the type of an expression must be statically determinable by the expression itself, regardless of context.
In other words, the type of an expression Test() cannot depend on what you're assigning it to.
Check C# Language Specification ยง7.5.2, the declaring type of a variable is not an attestation for type inference, and obviously it shouldn't be. Consider the following code:
Base b = Test<Derived>();
Derived d = Test<Derived>();
The return type of the method probably differs from the declaring type of the variable, since we have implicit convert in C#.
Type inference by the compiler doesn't use the "expected type" of an assignment as part of the logic.
So, the "scope of consideration" for type inference is not this:
SomeObject myObj = Test();
but this:
Test();
And, there are no clues here as to the expected type.
If you want an example of why the type of an expression needs to be able to be determined by the expression itself, consider the following two cases:
We don't use the return value at all - we're just calling the method for its side-effects.
We pass the return value directly into an overloaded method
Using the "expected type" of the return value when it comes to generic type resolution would introduce a whole whack of additional complexity into the compiler, and all you've gained is that sometimes you need to explicitly specify the type and sometimes you don't, and whether you need to or not can change based on unrelated changes elsewhere in the code.
Here the context for my question:
A common technique is to declare the parameter of a method as a Lambda expression rather than a delegate. This is so that the method can examine the expression to do interesting things like find out the names of method calls in the body of the delegate instance.
Problem is that you lose some of the intelli-sense features of Resharper. If the parameter of the method was declared as a delegate, Resharper would help out when writing the call to this method, prompting you with the x => x syntax to supply as the argument value to this method.
So... back to my question I would like to do the follow:
MethodThatTakesDelegate(s => s.Length);
}
private void MethodThatTakesDelegate(Func<string, object> func)
{
//convert func into expression
//Expression<Func<string, object>> expr = "code I need to write"
MethodThatTakesExpression(expr);
}
private void MethodThatTakesExpression(Expression<Func<string, object>> expr)
{
//code here to determine the name of the property called against string (ie the Length)
}
Everywhere that you're using the term "lambda expression" you actually mean "expression tree".
A lambda expression is the bit in source code which is
parameters => code
e.g.
x => x * 2
Expression trees are instances of the System.Linq.Expressions.Expression class (or rather, one of the derived classes) which represent code as data.
Lambda expressions are converted by the compiler into either expression trees (or rather, code which generates an expression tree at execution time) or delegate instances.
You can compile an instance of LambdaExpression (which is one of the subclasses of Expression) into a delegate, but you can't go the other way round.
In theory it might be possible to write such a "decompiler" based on the IL returned by MethodBase.GetMethodBody in some situations, but currently there are various delegates which can't be represented by expression trees. An expression tree represents an expression rather than a statement or statement block - so there's no looping, branching (except conditionals), assignment etc. I believe this may change in .NET 4.0, though I wouldn't expect a decompilation step from Microsoft unless there's a really good reason for one.
I don't believe it's possible to achieve what you'd like here. From the comments in your code it looks like you are attempting to capture the name of the property which did the assignment in MethodThatTakesExpression. This requires an expression tree lambda expression which captures the contexnt of the property access.
At the point you pass a delegate into MethodThatTakesDelegate this context is lost. Delegates only store a method address not any context about the method information. Once this conversion is made it's not possible to get it back.
An example of why this is not possible is that there might not even be a named method backing a delegate. It's possible to use ReflectionEmit to generate a method which has no name whatsoever and only exists in memory. It is possible though to assign this out to a Func object.
No, it is not possible.
I am trying to understand LINQ and become confident at using it. What I am struggling with are the parameters asked for. Example:
var sortedWords = words.OrderBy(a=>a.Length)
words is an array collection. OrderBy's intellisense says:
Func<string, TKey> keyselector
A func executes a method, and a string is the value, TKey a key.
In the example http://msdn.microsoft.com/en-us/vcsharp/aa336756.aspx#thenBySimple (ThenBy - Comparer), we compare length by saying a => a.Length. I understand that syntax, but how is that related to what the intellisense is asking for?
I tend to find the method signature and intellisense unreadable because of all the generics.
Thanks.
The type (as displayed by Intellisense) makes sense if you understand the nature of lambda expressions in .NET/C#. Otherwise, it can indeed seem a bit strange to the newcomer. Begin by considering that the type of keySelector, Func<TSource, TKey> is simply a delegate. Before C# 3.0, you would call such a method by passing a delegate as a parameter, for example:
IEnumerable<string> sortedWords = words.OrderBy(new Func<string, int>(mySelectorMethod));
where mySelectorMethod is the name of an ordinary method which takes a string as a parameter and returns an int. (As a side point, I suppose you could use anonymous delegates, but let's not go there for now.) Also, note that this example is purely illustrative, as LINQ is almost always used with .NET 3.5/C# 3.0 (though I believe it can be used with either/both .NET 2.0/C# 2.0 - someone correct me if I'm wrong). Since C# 3.0, methods can be defined inline as lambda expressions, which are intended to be used in precisely such circumstances as these. Read over the MSDN article on lambda expressions (linked above) if you want to get a proper introduction, but here I will simply describe the use in this specific context. As you state, your code (in C# 3.0) is something like the following:
var sortedWords = words.OrderBy(a => a.Length);
The part of the expression that is a => a.Length is the lambda expression, which is really just shorthand for declaring a function inline. The syntax of lambda expressions is quite simple for the most part; to the left of the => the arguments are specified, generally in the form (arg1, arg2, arg3), but since there's only one in this case you can omit the brackets. To the right of the => is the expression that is the return value of the function (lambda expression more accurately). Alternatively you can enclose actual code with a return statement within { and } though this is usually unnecessary. What I believe the C# compiler does is recognises the parameter passed to OrderBy as a lambda expression and then compiles it into a function and creates and passes the delegate for you. Note that lambda expressions can also be converted to System.Linq.Expressions.Expression objects (accessible expression trees) instead of delegates, but this is a much less common usage. Anyway, there's a lot going on behind the scenes here, but hopefully this should at least clarify why the type is Func<TSource, TKey> and how it relates to the lambda expression. As I said, read up on MSDN if you want a deeper understanding of LINQ/lambdas/delegates...
a => a.Length
I understand that syntax, but how is that related to what the intellisense is asking for?
This chunk of code is a lambda expression. A lambda expression is a handy way of generating an Anonymous method (in this case), or a System.Linq.Expressions.Expression . Let's break it down by parts.
The most noticeable feature is the =>, which seperates parameters from a method body.
On the left side of the =>, there is a symbol: a. This is the declaration of a parameter for our anonymous method. The compiler is aware that we are calling OrderBy(), and that OrderBy requires a Func<string, object>. The parameter for such a function is a string, so the compiler determines that a must be a string. The only thing the programmer needed to provide is a name.
On the right side of the =>, there is method body. Since this is a one-liner, the return keyword is implied. The IDE provides intellisense against a as a string, which allows you to use the Length property.
Now, consider this C# 2.0 ...
IEnumerable<string> sortedWords =
Enumerable.OrderBy(words, delegate(string a) {return a.Length;});
With the C# 3.0
IEnumerable<string> sortedWords = words
.OrderBy(a => a.Length);
I think the IntelliSense is actually quite useful, especially for generic methods that take Func<..> type as an argument, because you can see the types and types guide you to understand what the method might do.
For example, the arguments for OrderBy are IEnumerable<string> as a 'this' argument, which means that we have some input containing collection of strings. The first argument keySelector has a type Func<string, TKey>, which means that it is some lambda expression you provide that specifies how to get TKey from string.
This already suggests that the method will probably enumerate over all the items (strings) in the collection and it can use the keySelector to get value of type TKey from every element in the collection. The name TKey already suggests that it will use this value to compare the elements (strings) using this calculated key. However, if you look at the other overload that takes IComparer<TKey> then you can be sure about this - this argument specifies more details about how do you want to compare two values of type TKey, so the function must compare the elements using this key.
... this kind of thinking about types takes some time to get used to, but once you'll learn it, it can be extremely helpful. It is more useful in "functional" style of code, which often uses a lot of generics and lamdba expressions in C# 3.0 (and similar things in functional languages like F# or others)
I never really worry about the Intellisense, to be honest. It was messing me up early in my Linqage. As I spent more time with generics and expressions, it started to make sense, but up until then I just pumped in the syntax.
What it wants is a lambda expression that tells Linq what to look for in order to sort your collection.
I feel you, my brother, hang in there and it will make sense very soon.
OrderBy() takes a delegate for a function that accepts a single parameter (in your case, a string) and returns a value of the type that is substituted for TKey. It may be that the parameter type (string) was already determined since you called the method on an IEnumerable<string> but the delegate type will only be resolved as Func<string, int> after it infers it from the lambda expression when it is fully specified (i.e., a => a.Length). If you haven't given the parser any clues as to what you want as a sort key, it'll just show TKey in IntelliSense until it can determine the intended type.