C\#표현 식 트 리 Expression Trees 지식 정리
표현 식 트 리 는 트 리 데이터 구조 로 코드 를 표시 합 니 다.그 중에서 모든 노드 는 표현 식 입 니 다.예 를 들 어 방법 호출 과 x
표현 식 트 리 는 동적 언어 가 실 행 될 때(DLR)동적 언어 와.NET Framework 간 의 상호 작용 성 을 제공 하 는 데 도 사용 할 수 있 습 니 다.
1.Lambda 표현 식 생 성 표현 식 트 리
lambda 표현 식 이Expression<TDelegate>형식의 변수 에 할당 되면 컴 파일 러 는 이 lambda 표현 식 을 나타 내 는 표현 식 트 리 를 만 들 기 위해 코드 를 발사 할 수 있 습 니 다.
C\#컴 파 일 러 는 표현 식 lambda(또는 한 줄 lambda)에서 만 표현 식 트 리 를 생 성 할 수 있 습 니 다.
다음 코드 예제 에 서 는 키워드 Expression 을 사용 하여 lambda 표현 식 을 만 듭 니 다.
Expression<Action<int>> actionExpression = n => Console.WriteLine(n);
Expression<Func<int, bool>> funcExpression1 = (n) => n < 0;
Expression<Func<int, int, bool>> funcExpression2 = (n, m) => n - m == 0;
2.API 생 성 표현 식 트 리API 를 통 해 표현 식 트 리 를 만 들 려 면Expression클래스 를 사용 해 야 합 니 다.
다음 코드 예제 에 서 는 API 를 통 해 lambda 표현 식 을 만 드 는 방법 을 보 여 줍 니 다:num=>num==0
// Expression
// lambda:num => num == 0
ParameterExpression pExpression = Expression.Parameter(typeof(int)); // :num
ConstantExpression cExpression = Expression.Constant(0); // :0
BinaryExpression bExpression = Expression.MakeBinary(ExpressionType.Equal, pExpression, cExpression); // :num == 0
Expression<Func<int, bool>> lambda = Expression.Lambda<Func<int, bool>>(bExpression, pExpression); //lambda :num => num == 0
코드 는Expression류 의 정적 방법 으로 생 성 됩 니 다.3.해석 식 트 리
다음 코드 예제 에 서 는 lambda 표현 식 num=>num==0 을 나타 내 는 표현 식 트 리 를 어떻게 분해 하 는 지 보 여 줍 니 다.
Expression<Func<int, bool>> funcExpression = num => num == 0;
//
ParameterExpression pExpression = funcExpression.Parameters[0]; //lambda
BinaryExpression body = (BinaryExpression)funcExpression.Body; //lambda :num == 0
Console.WriteLine($" :{pExpression.Name} => {body.Left} {body.NodeType} {body.Right}");
4.표현 식 트 리 영구적
표현 식 트 리 는 영구적(문자열 과 유사)이 어야 합 니 다.이것 은 표현 식 트 리 를 수정 하려 면 이 표현 식 트 리 를 복사 한 다음 노드 를 바 꾸 어 새로운 표현 식 트 리 를 만들어 야 한 다 는 것 을 의미 합 니 다. 표현 식 트 리 를 사용 하여 방문 자 들 이 기 존 표현 식 트 리 를 옮 겨 다 닐 수 있 습 니 다.7 절 은 표현 식 트 리 를 어떻게 수정 하 는 지 소개 했다.
5.컴 파일 식 트 리
Expression<TDelegate>형식 은 표현 식 트 리 가 표시 하 는 코드 를 실행 가능 한 의뢰 로 컴 파일 하 는 방법 을 제공 합 니 다.
//
Expression<Func<string, int>> funcExpression = msg => msg.Length;
//
var lambda = funcExpression.Compile();
//
Console.WriteLine(lambda("Hello, World!"));
//
Console.WriteLine(funcExpression.Compile()("Hello, World!"));
6.표현 식 트 리 실행
표현 식 트 리 를 실행 하면 값 을 되 돌려 줄 수도 있 고,한 동작 만 수행 할 수도 있 습 니 다.(예 를 들 어 호출 방법)
lambda 표현 식 을 표시 하 는 표현 식 트 리 만 실행 할 수 있 습 니 다.lambda 표현 식 을 나타 내 는 표현 식 트 리 는Compile또는LambdaExpression형식 에 속 합 니 다.이 표현 식 트 리 를 실행 하려 면 실행 가능 한 의뢰 를 만 들 고 이 의뢰 를 호출 하 는 방법Expression<TDelegate>을 사용 해 야 합 니 다.
const int n = 1;
const int m = 2;
//
BinaryExpression bExpression = Expression.Add(Expression.Constant(n), Expression.Constant(m));
// lambda
Expression<Func<int>> funcExpression = Expression.Lambda<Func<int>>(bExpression);
// lambda
Func<int> func = funcExpression.Compile();
// lambda
Console.WriteLine($"{n} + {m} = {func()}");
7.표현 식 트 리 수정
이 클래스 계승Compile클래스,Visit 방법 을 통 해 VisitBinary 방법 을 간접 적 으로 호출 합 니 다!==로 바꾸다.기본 적 인 방법 은 들 어 오 는 표현 식 트 리 와 유사 한 노드 를 구성 하지만 이 노드 들 은 하위 디 렉 터 리 트 리 를 방문 기 재 귀적 으로 생 성 된 표현 식 트 리 로 대체 합 니 다.
internal class Program
{
private static void Main(string[] args)
{
Expression<Func<int, bool>> funcExpression = num => num == 0;
Console.WriteLine($"Source: {funcExpression}");
var visitor = new NotEqualExpressionVisitor();
var expression = visitor.Visit(funcExpression);
Console.WriteLine($"Modify: {expression}");
Console.Read();
}
/// <summary>
///
/// </summary>
public class NotEqualExpressionVisitor : ExpressionVisitor
{
public Expression Visit(BinaryExpression node)
{
return VisitBinary(node);
}
protected override Expression VisitBinary(BinaryExpression node)
{
return node.NodeType == ExpressionType.Equal
? Expression.MakeBinary(ExpressionType.NotEqual, node.Left, node.Right) // : != ==
: base.VisitBinary(node);
}
}
}
8.디 버 깅
8.1 매개 변수 표현 식
ParameterExpression pExpression1 = Expression.Parameter(typeof(string));
ParameterExpression pExpression2 = Expression.Parameter(typeof(string), "msg");
그림 8-1
그림 8-2
DebugView 에서 알 수 있 듯 이 매개 변수 에 이름 이 없 으 면 자동 으로 생 성 된 이름 을 할당 합 니 다.
const int num1 = 250;
const float num2 = 250;
ConstantExpression cExpression1 = Expression.Constant(num1);
ConstantExpression cExpression2 = Expression.Constant(num2);
그림 8-3
그림 8-4
DebugView 에서 알 수 있 듯 이 float 는 int 보다 접미사 F 가 많 습 니 다.
Expression lambda1 = Expression.Lambda<Func<int>>(Expression.Constant(250));
Expression lambda2 = Expression.Lambda<Func<int>>(Expression.Constant(250), "CustomName", null);
그림 8-5
그림 8-6
DebugView 를 관찰 하면 lambda 표현 식 에 이름 이 없 으 면 자동 으로 생 성 된 이름 을 할당 합 니 다.
이상 은 본 고의 모든 내용 입 니 다.본 고의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 도움 이 되 기 를 바 랍 니 다.또한 저 희 를 많이 지지 해 주시 기 바 랍 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
WebView2를 Visual Studio 2017 Express에서 사용할 수 있을 때까지Evergreen .Net Framework SDK 4.8 VisualStudio2017에서 NuGet을 사용하기 때문에 패키지 관리 방법을 packages.config 대신 PackageReference를 사용해야...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.