c# 람다식 - 형식 멤버에 대한식이 다른 식(MemberExpression, UnaryExpression)




함수 인라인 (3)

그 이유는 Age 유형이기 때문입니다. 값 유형을 반환하는 표현식을 Func<Person,object> 로 강요하기 위해 컴파일러는 Convert(expr, typeof(object)) , UnaryExpression 을 삽입해야합니다.

그러나 string 및 기타 참조 유형의 경우 상자를 만들 필요가 없으므로 "직선"멤버 표현식이 반환됩니다.

UnaryExpression 내에서 MemberExpression 을 얻으려면 피연산자를 얻을 수 있습니다.

private static MemberExpression GetMemberExpression<T>(
    Expression<Func<T,object>> exp
) {
    var member = exp.Body as MemberExpression;
    var unary = exp.Body as UnaryExpression;
    return member ?? (unary != null ? unary.Operand as MemberExpression : null);
}

기술

내 유형의 속성을 가리키는 표현이 있습니다. 그러나 모든 속성 유형에 대해 작동하지는 않습니다. "의미하지는 않습니다"는 결과가 다른 표현 유형을 의미합니다. 나는 그것이 MemberExpression 결과로 가져올 것이라고 생각했지만 이것은 그렇지 않습니다.

intGuid 경우 UnaryExpression 되고, MemberExpression string 됩니다.

나는 조금 혼란 스럽다.)

일부 샘플 코드

내 수업

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

테스트 코드

Person p = new Person { Age = 16, Name = "John" };

Expression<Func<Person, object>> expression1 = x => x.Age;
// expression1.Body = UnaryExpression;

Expression<Func<Person, object>> expression2 = x => x.Name;
// expression2.Body = MemberExpression;

문제

두 표현식을 비교하고 그들이 동일한 유형 및 동일한 속성을 의미하는지 확인하려면 어떻게해야합니까?

업데이트, 샘플 응답 및 완료

누가 나를 올바른 길로 인도했는지 사용자 dasblinkenlight 에게 감사드립니다.

그는 방법을 제공했다.

private static MemberExpression GetMemberExpression<T>(
    Expression<Func<T,object>> exp
) {
    var member = expr.Body as MemberExpression;
    var unary = expr.Body as UnaryExpression;
    return member ?? (unary != null ? unary.Operand as MemberExpression : null);
}

다음 확장 메서드를 작성하여 GetMemberExpression 메서드의 결과를 비교하고 GetMemberExpression().Member.Name 이 동일한 지 확인합니다.

private static bool IsSameMember<T>(this Expression<Func<T, object>> expr1, Expression<Func<T, object>> expr2)
{
    var result1 = GetMemberExpression(expr1);
    var result2 = GetMemberExpression(expr2);

    if (result1 == null || result2 == null)
       return false;

    return result1.Member.Name == result2.Member.Name;
}

Member.Name 문자열을 비교하는 대신 고유 클래스의 두 속성이 같은 이름을 공유하는 경우 오탐 (false positives)을 피하기 위해 PropertyInfo 인스턴스를 직접 비교하여 같음을 제안하는 것이 좋습니다.

public static bool IsSameProperty<TSourceA, TSourceB, TPropertyA, TPropertyB>(
    Expression<Func<TSourceA, TPropertyA>> expA,
    Expression<Func<TSourceB, TPropertyB>> expB)
{
    MemberExpression memExpA = expA.Body as MemberExpression;
    MemberExpression memExpB = expB.Body as MemberExpression;

    if (memExpA == null || memExpB == null)
        return false;

    PropertyInfo propA = memExpA.Member as PropertyInfo;
    PropertyInfo propB = memExpB.Member as PropertyInfo;

    if (propA == null || propB == null)
        return false;

    return propA.Equals(propB);
}

Expression<Func<T, TResult>> 표현식의 제네릭 형식 TResult 로 올바른 값 형식 ( object 가 아닌)을 지정하는 것만으로 람다식이 UnaryExpression 아닌 MemberExpression 컴파일되도록 할 수 있습니다.

Expression<Func<Person, int>> expression1 = x => x.Age;
Expression<Func<Person, int>> expression2 = x => x.Age;
Expression<Func<Person, string>> expression3 = x => x.Name;

Console.WriteLine(IsSameProperty(expression1, expression2));   // True
Console.WriteLine(IsSameProperty(expression1, expression3));   // False

요약 기능 :

  1. 추상 클래스 내에서만 선언 할 수 있습니다.
  2. 여기에는 추상 클래스의 구현이 아닌 메소드 선언 만 포함됩니다.
  3. 파생 클래스에서 재정의해야합니다.

가상 기능 :

  1. 추상 클래스뿐만 아니라 추상 클래스 내에서 선언 될 수 있습니다.
  2. 메소드 구현을 포함합니다.
  3. 재정의 될 수 있습니다.






c# .net lambda expression