[C#] Vergelijken van LINQ Expression Trees

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
Is er standaard functionaliteit binnen .NET aanwezig om expression trees met elkaar te vergelijken?

Voorbeeld:
C#:
1
2
Expression<Func<Person, object>> expression1 = p1 => p1.LastName;
Expression<Func<Person, object>> expression2 = p2 => (p2.LastName);


Qua naamgeving en haakjes verschillen de variabelen in de lambda expressie maar ze leveren uiteindelijk hetzelfde resultaat. Een standaard p1 == p2 gaat natuurlijk niet werken aangezien de referentie anders is. Moet ik de hele tree normalizeren en doorlopen voordat ik er iets zinnigs mee kan doen?

PSN: Norfirin


Acties:
  • 0 Henk 'm!

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Je zou .ToString() kunnen overwegen en de strings vergelijken. Dit zou in veel gevallen genoeg moeten zijn. Met een visitor de tree doorlopen is niet eenvoudig in de zin van 'ik vergelijk even twee trees door een visitor eroverheen te laten lopen', want hoe ga je posities vergelijken? Dat is echt heel lastig.

Die haakjes zijn overigens niet zichtbaar in de tree, dus als het je daar om te doen is kun je je het werk besparen ;)

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Acties:
  • 0 Henk 'm!

  • FireDrunk
  • Registratie: November 2002
  • Laatst online: 16:42
Wat wil je precies vergelijken? Want je kunt de expression gewoon uitlezen...

expression.MemerExpression bevat meestal gewoon wat je nodig hebt?

Even niets...


Acties:
  • 0 Henk 'm!

  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
Je zult eerst een voor jezelf moeten definieren wanneer twee expressies gelijk zijn.

Is (a + (b + c)) gelijk aan ((a + b) + c), om maar iets te noemen.

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


Acties:
  • 0 Henk 'm!

  • Phyxion
  • Registratie: April 2004
  • Niet online

Phyxion

_/-\o_

Tony L schreef op donderdag 08 juli 2010 @ 10:19:
Is er standaard functionaliteit binnen .NET aanwezig om expression trees met elkaar te vergelijken?

Voorbeeld:
C#:
1
2
Expression<Func<Person, object>> expression1 = p1 => p1.LastName;
Expression<Func<Person, object>> expression2 = p2 => (p2.LastName);


Qua naamgeving en haakjes verschillen de variabelen in de lambda expressie maar ze leveren uiteindelijk hetzelfde resultaat. Een standaard p1 == p2 gaat natuurlijk niet werken aangezien de referentie anders is. Moet ik de hele tree normalizeren en doorlopen voordat ik er iets zinnigs mee kan doen?
Zo goed ik mij kan herinneren is er gewoon een Expression.Equals(expression1, expression2).

'You like a gay cowboy and you look like a gay terrorist.' - James May


Acties:
  • 0 Henk 'm!

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Phyxion schreef op donderdag 08 juli 2010 @ 13:01:
[...]

Zo goed ik mij kan herinneren is er gewoon een Expression.Equals(expression1, expression2).
Nope.

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Acties:
  • 0 Henk 'm!

  • Phyxion
  • Registratie: April 2004
  • Niet online

Phyxion

_/-\o_

Volgens MSDN anders wel, alleen is het .Equal ipv .Equals.

'You like a gay cowboy and you look like a gay terrorist.' - James May


Acties:
  • 0 Henk 'm!

  • RayNbow
  • Registratie: Maart 2003
  • Laatst online: 20:37

RayNbow

Kirika <3

Phyxion schreef op donderdag 08 juli 2010 @ 15:52:
[...]

Volgens MSDN anders wel, alleen is het .Equal ipv .Equals.
Lees de beschrijving eens?
Creates a BinaryExpression that represents an equality comparison.

Ipsa Scientia Potestas Est
NNID: ShinNoNoir


Acties:
  • 0 Henk 'm!

  • Sebazzz
  • Registratie: September 2006
  • Laatst online: 19:03

Sebazzz

3dp

Phyxion schreef op donderdag 08 juli 2010 @ 15:52:
[...]

Volgens MSDN anders wel, alleen is het .Equal ipv .Equals.
Niet precies. Dat maakt een vergelijking aan voor de uitkomst van de expressies.

[Te koop: 3D printers] [Website] Agile tools: [Return: retrospectives] [Pokertime: planning poker]


Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
Mmm, ik denk dat ik mezelf in de nesten ga werken als ik daadwerkelijk de boel ga normalizeren. Hoe meer argumenten hoe meer werk het gaat worden.

@EfBe
Jouw manier zou ik zeker gebruiken als ik de argument namen kon aanpassen.

C#:
1
2
3
4
5
6
7
8
9
10
        public static string GenerateExpressionName(Expression<Func<T, object>> expr) {
            IList<ParameterExpression> parameters = new List<ParameterExpression>();
            int character = 97;
            foreach (ParameterExpression parameter in expr.Parameters) {
                ParameterExpression newParameter = Expression.Parameter(parameter.Type, ((char) character++).ToString());
                parameters.Add(newParameter);
            }           
            Expression<Func<T, object>> newExpr = Expression.Lambda<Func<T, object>>(expr.Body, parameters.ToArray());
            return newExpr.ToString();
        }


Dit werkt helaas niet omdat hij alleen de parameter aanpast en niet de rest.

s => s.LastName

wordt dan

a => s.LastName

Daar kan ik dus niet zoveel mee en om die hele tree door te lopen en opnieuw op te bouwen gaat me ook een beetje ver. Ik denk dat ik maar een naming conventie gebruik door altijd te beginnen met argument "a" en dan "b", etc. Niet echt de mooiste oplossing denk ik maar er zijn weinig andere opties :/

PSN: Norfirin


Acties:
  • 0 Henk 'm!

  • EfBe
  • Registratie: Januari 2000
  • Niet online
Tony L schreef op donderdag 08 juli 2010 @ 21:16:
Mmm, ik denk dat ik mezelf in de nesten ga werken als ik daadwerkelijk de boel ga normalizeren. Hoe meer argumenten hoe meer werk het gaat worden.

@EfBe
Jouw manier zou ik zeker gebruiken als ik de argument namen kon aanpassen.

C#:
1
2
3
4
5
6
7
8
9
10
        public static string GenerateExpressionName(Expression<Func<T, object>> expr) {
            IList<ParameterExpression> parameters = new List<ParameterExpression>();
            int character = 97;
            foreach (ParameterExpression parameter in expr.Parameters) {
                ParameterExpression newParameter = Expression.Parameter(parameter.Type, ((char) character++).ToString());
                parameters.Add(newParameter);
            }           
            Expression<Func<T, object>> newExpr = Expression.Lambda<Func<T, object>>(expr.Body, parameters.ToArray());
            return newExpr.ToString();
        }


Dit werkt helaas niet omdat hij alleen de parameter aanpast en niet de rest.

s => s.LastName

wordt dan

a => s.LastName

Daar kan ik dus niet zoveel mee en om die hele tree door te lopen en opnieuw op te bouwen gaat me ook een beetje ver. Ik denk dat ik maar een naming conventie gebruik door altijd te beginnen met argument "a" en dan "b", etc. Niet echt de mooiste oplossing denk ik maar er zijn weinig andere opties :/
Dat kan wel, je moet nl de Lambda converten: die heeft een parameter (of parameters) en die parameters moet je renamen, en die _instances_ moet je ook gebruiken ipv de parameters die je had. Dus heb je eerst parameters a en b, en wil je nu x en y, dan maak je ze aan in de lambda en vervang je ze in de body mbv een visitor.

Het is idd vrij lastig, dus de vraag rijst dan natuurlijk: waarom deze moeite doen... :) (en om de moed helemaal in de schoenen te krijgen: VB.NET genereert soms andere expression trees dan C# ;))

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Acties:
  • 0 Henk 'm!

  • Tony L
  • Registratie: September 2005
  • Laatst online: 07-11-2015
EfBe schreef op vrijdag 09 juli 2010 @ 09:04:
[...]

Dat kan wel, je moet nl de Lambda converten: die heeft een parameter (of parameters) en die parameters moet je renamen, en die _instances_ moet je ook gebruiken ipv de parameters die je had. Dus heb je eerst parameters a en b, en wil je nu x en y, dan maak je ze aan in de lambda en vervang je ze in de body mbv een visitor.

Het is idd vrij lastig, dus de vraag rijst dan natuurlijk: waarom deze moeite doen... :) (en om de moed helemaal in de schoenen te krijgen: VB.NET genereert soms andere expression trees dan C# ;))
Ik had ook wel de indruk dat het mogelijk was hoor :). Ik heb nog een beetje lopen stoeien maar het is de moeite niet waard. De complexiteit is groter dan de winst die het oplevert dus dan gebruik ik liever een naming conventie ;)

Interessant dat VB.NET andere expression trees kan genereren in vergelijking met C#. Je zou denken dat dezelfde logica achter de opbouw van een expression tree zou zitten. Als ik het "mooi" zou willen doen dan zou de expressie tree structuur die ik meegeef, precies dezelfde structuur moeten zijn als degene die ik terug krijg. Het enige verschil zijn dan de parameter namen. Met een visitor pattern zou dit zeker gaan werken maar het werkt nu al met alleen een naming conventie ;)

Thanks heren voor jullie reacties!

PSN: Norfirin

Pagina: 1