Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lambda Expression `x => x.Property` gets changed to `x => Convert(x.Property)`

Tags:

c#

object

lambda

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.

like image 734
Arthur Rey Avatar asked Oct 13 '15 10:10

Arthur Rey


People also ask

How do you convert lambda expressions?

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.

What is the use of => in C#?

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.

What is lambda expression in C# with example?

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 .

What is lambda expression in LINQ?

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.


2 Answers

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.

OP said...

Isn't there any way to force the Expression to remain untouched?

No. You should handle both scenarios: accessing properties with and without casts.

like image 116
Matías Fidemraizer Avatar answered Nov 15 '22 18:11

Matías Fidemraizer


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.

like image 31
qxg Avatar answered Nov 15 '22 19:11

qxg