I have a sample Data
class
public class Data
{
public int TestInt { get; set; }
public bool TestBool { get; set; }
public string TestString { get; set; }
public Data() { TestInt = 10; TestBool = true; TestString = "test"; }
}
And an extension method
public static void Method<T>(this T item, params Expression<Func<T, object>>[] properties)
{
/* Some stuff */
}
That I use like this
Data data = new Data();
data.Method(x => x.TestInt, x => x.TestBool, x => x.TestString);
My Method<T>
does receive 3 properties, but it has been slightly changed to:
properties[0] = x => Convert(x.TestId);
properties[1] = x => Convert(x.TestBool);
properties[2] = x => x.TestString;
As you can see, the TestString
part is unchanged. I tried changing my properties to params Expression<Func<T, bool>>[]
and params Expression<Func<T, int>>[]
and only pass the corresponding parameter and it works fine. I understand the problem comes from converting into an object
but I can't figure it out.
To convert a lambda expression to a named methodMove to the labda expression you want to convert. From the Refactor menu of the VisualAid choose To Named Method. Telerik® JustCode™ will replace the lambda expression with a method group and will add a new method.
The => token is supported in two forms: as the lambda operator and as a separator of a member name and the member implementation in an expression body definition.
The expression num => num * 5 is a lambda expression. The => operator is called the "lambda operator". In this example, num is an input parameter to the anonymous function, and the return value of this function is num * 5 . So when multiplyByFive is called with a parameter of 7 , the result is 7 * 5 , or 35 .
The term 'Lambda expression' has derived its name from 'lambda' calculus which in turn is a mathematical notation applied for defining functions. Lambda expressions as a LINQ equation's executable part translate logic in a way at run time so it can pass on to the data source conveniently.
Since both Int32
and Boolean
aren't reference types, the whole expression tree needs to explicitly cast them to object
.
There're some implicit operations that are available during compile-time using regular C# compiler while others require explicit actions while implementing expression trees.
Do you want to test yourself about this fact?
public struct A {}
public class B { }
public class C
{
public A A { get; set; }
public B B { get; set; }
}
C c = new C();
Expression<Func<C, object>> expr1 = some => some.A; // Convert(some.A)
Expression<Func<C, object>> expr2 = some => some.B; // some.B
At the end of the day, regular C# compiler implements some trickery to cast a value type to fit into object
(a reference type). Maybe this Q&A "How do ValueTypes derive from Object (ReferenceType) and still be ValueTypes?" where Eric Lippert answered it might be interesting for you.
Isn't there any way to force the Expression to remain untouched?
No. You should handle both scenarios: accessing properties with and without casts.
If you want to analyze original expression, one possible way is to remove Convert
expression manually.
In Method
, you may get a UnaryExpression
with NodeType
= Convert
. If so, just inspect this expression's Operand property.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With