將對象放入單元素數組,用 Select 投影屬性,Expression.Lambda 動態編譯委託,緩存複用。比反射快 10 倍+,比直接訪問慢但可動態。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Diagnostics;
public class QuickAccess
{
static readonly Dictionary _cache = new Dictionary();
static readonly T[] _single = new T[1];
public static P GetPropertyValue(T obj, string propertyName)
{
_single[0] = obj;
int key = propertyName.GetHashCode();
if (!_cache.TryGetValue(key, out Delegate func))
{
// 動態構建:param => param.PropertyName
ParameterExpression param = Expression.Parameter(typeof(T), "param");
MemberExpression body = Expression.Property(param, propertyName);
LambdaExpression lambda = Expression.Lambda(body, param);
func = lambda.Compile();
_cache[key] = func;
}
return _single.Select((Func)func).First();
}
}
// 使用示例
class User { public string Name { get; set; } public int Age { get; set; } }
var user = new User { Name = "Lucifer", Age = 26 };
var sw = Stopwatch.StartNew();
for (int i = 0; i < 10_000_000; i++)
int val = QuickAccess.GetPropertyValue(user, "Age");
sw.Stop();
Console.WriteLine($"Elapsed: {sw.ElapsedMilliseconds} ms");
| 方式 | 耗時 | 相對性能 |
|---|---|---|
直接訪問 user.Age | ~30 ms | 1.0x (基準) |
| Expression 快取 | ~120 ms | 4x 慢 |
反射 PropertyInfo.GetValue | ~1500 ms | 50x 慢 |
動態 dynamic | ~800 ms | 27x 慢 |