C\#고성능 동적 으로 대상 속성 값 을 가 져 오 는 절차
public class People
{
public string Name { get; set; }
}
그리고 직접 코드 호출 방식 으로 천만 번 을 찾 으 려 면 얼마나 걸 리 는 지 보 세 요.
private static void Directly()
{
People people = new People { Name = "Wayne" };
Stopwatch stopwatch = Stopwatch.StartNew();
for (int i = 0; i < 10000000; i++)
{
object value = people.Name;
}
stopwatch.Stop();
Console.WriteLine("Directly: {0}ms", stopwatch.ElapsedMilliseconds);
}
약 37ms 가 들 었 습 니 다.반사
반 사 를 통 해 대상 의 속성 치 를 얻 는 것 은 모두 가 자주 사용 하 는 방식 이 어야 하지만 이런 방식 의 성능 은 비교적 떨어진다.다음은 똑 같이 천만 번 을 찾 는 데 시간 이 얼마나 걸 리 는 지 살 펴 보 자.
private static void Reflection()
{
People people = new People { Name = "Wayne" };
Type type = typeof(People);
PropertyInfo property = type.GetProperty("Name");
Stopwatch stopwatch = Stopwatch.StartNew();
for (int i = 0; i < 10000000; i++)
{
object value = property.GetValue(people);
}
stopwatch.Stop();
Console.WriteLine("Reflection: {0}ms", stopwatch.ElapsedMilliseconds);
}
1533 ms 정도 들 었 는데 역시 많이 느 려 야 해 요.그렇다면 반사 가 느 린 이상 다른 방법 은 없 을 까?
동적 구축 람 다
Linq 의 Lambda 표현 식 을 동적 으로 구축 할 수 있다 는 것 을 알 고 컴 파일 을 통 해 의뢰 를 받 았 습 니 다.속성 값 을 되 돌려 주 는 의뢰 를 동적 으로 구축 할 수 있다 면 값 을 얻 을 수 있 습 니 다.그래서 우 리 는 이런 의뢰 를 구축 할 방법 을 생각 했다.
Func<People, object> getName = m => m.Name;
다음은 Expression 을 통 해 구축 하 겠 습 니 다.
private static void Lambda()
{
People people = new People { Name = "Wayne" };
Type type = typeof(People);
var parameter = Expression.Parameter(type, "m");// m
PropertyInfo property = type.GetProperty("Name");
Expression expProperty = Expression.Property(parameter, property.Name);// m.Name
var propertyDelegateExpression = Expression.Lambda(expProperty, parameter);// m => m.Name
var propertyDelegate = (Func<People, object>)propertyDelegateExpression.Compile();//
Stopwatch stopwatch = Stopwatch.StartNew();
for (int i = 0; i < 10000000; i++)
{
object value = propertyDelegate.Invoke(people);
}
stopwatch.Stop();
Console.WriteLine("Lambda:{0}ms", stopwatch.ElapsedMilliseconds);
}
그리고 우리 가 테스트 해 보 자.대략 138 ms 가 들 었 는데 성능 이 반사 보다 훨씬 좋다.호출 을 의뢰 하 다
동적 구축 람 다 의 성능 은 이미 좋 지만 그래도 더 좋 습 니까?직접 호출 하 는 것 보다 못 하 니까 속성 을 직접 호출 하 는 수치 방법 이 있 었 으 면 좋 겠 어 요.
C\#에서 읽 을 수 있 는 속성 은 모두 대응 하 는 get 이 있 습 니 다.XXX()의 방법 은 이 방법 을 호출 하여 해당 속성의 값 을 얻 을 수 있 습 니 다.System.delegate.CreateDelegate 를 사용 하여 이 방법 을 호출 하 는 의뢰 를 만 들 수 있 습 니 다.
4.567917.위탁 호출 방법 을 통 해 속성 치 를 얻는다저 희 는 MemberGetDelegate 의 의뢰 를 정의 한 다음 에 이 를 통 해 값 을 추출 하 는 방법 을 호출 합 니 다.
delegate object MemberGetDelegate(People p);
private static void Delegate()
{
People people = new People { Name = "Wayne" };
Type type = typeof(People);
PropertyInfo property = type.GetProperty("Name");
MemberGetDelegate memberGet = (MemberGetDelegate)System.Delegate.CreateDelegate(typeof(MemberGetDelegate), property.GetGetMethod());
Stopwatch stopwatch = Stopwatch.StartNew();
for (int i = 0; i < 10000000; i++)
{
object value = memberGet(people);
}
stopwatch.Stop();
Console.WriteLine("Delegate: {0}ms", stopwatch.ElapsedMilliseconds);
}
그리고 테스트 를 해 보 겠 습 니 다.약 38ms 가 들 었 고 성능 은 거의 직접 호출 과 일치 합 니 다.마지막 으로 만 든 Delegate 를 캐 시 하 는 간단 한 패 키 징 을 만 듭 니 다.
public class PropertyValue<T>
{
private static ConcurrentDictionary<string, MemberGetDelegate> _memberGetDelegate = new ConcurrentDictionary<string, MemberGetDelegate>();
delegate object MemberGetDelegate(T obj);
public PropertyValue(T obj)
{
Target = obj;
}
public T Target { get; private set; }
public object Get(string name)
{
MemberGetDelegate memberGet = _memberGetDelegate.GetOrAdd(name, BuildDelegate);
return memberGet(Target);
}
private MemberGetDelegate BuildDelegate(string name)
{
Type type = typeof(T);
PropertyInfo property = type.GetProperty(name);
return (MemberGetDelegate)Delegate.CreateDelegate(typeof(MemberGetDelegate), property.GetGetMethod());
}
}
이렇게 사용 하면 훨씬 편리 하 다
People people = new People { Name = "Wayne" };
PropertyValue<People> propertyValue = new PropertyValue<People>(people);
object value = propertyValue.Get("Name");
이상 은 C\#고성능 동적 으로 대상 속성 값 을 얻 는 절차 의 상세 한 내용 입 니 다.c\#대상 속성 값 을 얻 는 데 관 한 자 료 는 다른 관련 글 을 주목 하 십시오!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
C#Task를 사용하여 비동기식 작업을 수행하는 방법라인이 완성된 후에 이 라인을 다시 시작할 수 없습니다.반대로 조인(Join)만 결합할 수 있습니다 (프로세스가 현재 라인을 막습니다). 임무는 조합할 수 있는 것이다. 연장을 사용하여 그것들을 한데 연결시키는 것이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.