2009-03-23 3 views
39

두 표현식이 같은지 확인할 수 있습니까?Expression <Func <T, bool>> 두 개가 같은지 확인하는 방법

처럼 주어진 다음 네 가지 표현 : 다음

 Expression<Func<int, bool>> a = x => false; 
     Expression<Func<int, bool>> b = x => false; 
     Expression<Func<int, bool>> c = x => true; 
     Expression<Func<int, bool>> d = x => x == 5; 

, 적어도 우리는 것을 볼 수 있습니다

  • a == b
  • a != c
  • a != d

내 코드에서이를 알아 내기 위해 무엇인가 할 수 있습니까? 지정한 Object가 현재 Object와 같은지 여부를 확인합니다 :

Equals는 것을 말한다 MSDN 라이브러리에 슬쩍했다. (Object에서 상 속됨)

나는 적어도 Expression 클래스가 equals 메서드를 Equatable 메서드보다 우선하지 않는다는 것을 의미한다고 생각합니까? 그러면 어떻게 할 수 있니? 아니면 내가 여기서 너무 많이 묻는거야? : p

+0

거기에 참여하는 'MemberInfo'가 있다면, 나는 필드의 속성을 의미합니다. 그러면 먼저 memberinfo를 얻고 그 해시를 계산할 수 있습니다. – nawfal

답변

32

Linq to db4o 내부에서 사용되는 ExpressionEqualityComparer 유형을 살펴볼 수 있습니다. 인터페이스 IEqualityComparer <T>을 구현하므로 일반 콜렉션뿐만 아니라 독립형 사용에도 유용합니다.

ExpressionComparison 형식을 사용하여 두 표현식을 비교하여 같음을 확인하고 HashCodeCalculation을 사용하여 표현식에서 해시 코드를 계산합니다.

모두 표현 트리를 방문해야하므로 반복적으로 계산하면 비용이 많이 들지만 꽤 편리 할 수도 있습니다.

코드는 여기에, GPL 또는 인스턴스에 대한 dOCL

에서 사용할 수 있습니다 테스트입니다 :

using System; 
using System.Linq.Expressions; 

using Db4objects.Db4o.Linq.Expressions; 

class Test { 

    static void Main() 
    { 
     Expression<Func<int, bool>> a = x => false; 
     Expression<Func<int, bool>> b = x => false; 
     Expression<Func<int, bool>> c = x => true; 
     Expression<Func<int, bool>> d = x => x == 5; 

     Func<Expression, Expression, bool> eq = 
      ExpressionEqualityComparer.Instance.Equals; 

     Console.WriteLine (eq (a, b)); 
     Console.WriteLine (eq (a, c)); 
     Console.WriteLine (eq (a, d)); 
    } 
} 

그리고 그것은 참으로 거짓, 거짓, 참 인쇄합니다.

+0

유망 해 보이지만,이 ExpressionComparison (a, b) .AreEqual 및 HashCodeCalculation (expression) .HashCode는 무엇입니까? – Svish

+1

구현을 찾아 볼 수 있으며, 동일한 폴더에 있습니다. –

+0

나는 내가 알아 내려고 시도하는 것을 해결하는 또 다른 방법을 찾으려고 노력할 것이라고 생각한다. 그러나 당신의 답은 실용적인 솔루션을 제공하는 것으로 보이므로 Accepted =로 표시 할 것이다. – Svish

4

가장 간단한 경우를 제외하고는이 작업이 어려울 수 있다고 생각납니다. 예를 들어

:

var numbers1 = Enumerable.Range(1, 20); 
Expression<Func<int, IEnumerable<int>>> a = x => numbers1; 
var numbers2 = Enumerable.Range(1, 20); 
Expression<Func<int, IEnumerable<int>>> b = x => numbers2; 

기술적으로, 이들은 동일하지만, 어떻게이 IEnuemrable을 평가하지 않고 결정 각 표현에 반환 될 수 있을까?

+1

여기에 여러분에게 묻습니다 : p hehe. 그러나 그렇습니다, 나는 문제를 볼 수있다. 그러나 나는 또한 볼 수있다. 그것을 보지 마라. 네가 말했듯이, 기술적 인면에서는 사실 동등하다. 그리고 적어도 하나의 표현식 트리는 노드와 데이터 유형에 따라 다른 표현식 트리와 비교되어야한다고 생각합니다. – Svish

+4

당신의 예제에서는 같지 않은 객체에 대한 참조를 포함하고 있기 때문에 그러한 표현식이 동일하지 않다고 생각했을 수도 있습니다 ... – Svish

+0

numbers1 또는 numbers2는 같은 값이 아닌 ConstantExpression 노드로 직렬화됩니다 . –

11

게으름 응답으로 ToString()을 확인할 수 있습니다 - 적어도 분명히 다른 위치를 표시해야합니다 (거기에는 var-name이 포함되어 있으므로 동일해야 함).

정확하게 동등한 검사를 위해 ... 훨씬 더 많은 노력 - 다양한 노드 유형에서 작동합니다.

+0

Lol, 이제는 실제로 일종의 ... D – Svish

+2

아니요, 모든 표현에 usab이있는 것은 아닙니다. 르 문자열 표현. 예를 들어 변환은 변환 할 유형을 나타내지는 않습니다. –

+2

정확히 - 나는 분명히 잘못된 대답을 발견 할 것이라고 말했지만, 그것에 관한 내용입니다. 나무를 제대로 걸어야하고 사용 된 실제 운영자를 확인해야 철저한 업무를 수행해야합니다. –