表现动态与反思

Ole*_*ers 6 c# linq reflection performance dynamic

我有以下可能性来检索列表中的值:

使用反射:

foreach (var item in items) {
  var property=item.Fields[fieldName].GetType().GetProperty("Id");
  var value=property.GetValue(item.Fields[fieldName]);
  if (value==searchValue) {
      filtered.Add(item);
   }
}
Run Code Online (Sandbox Code Playgroud)

使用动态:

foreach (var item in items) {
   dynamic itemProperty=item.Fields[fieldName];
   if (itemProperty.Id==searchValue) {   
      filtered.Add(item);
   }
}
Run Code Online (Sandbox Code Playgroud)

两个循环都是一样的.它们按字段[fieldName]过滤IEnumerable(或List),它可以是不同类型但都包含名为"Id"的int属性.

我想知道哪一个会有更好的表现.另外:将其中一个更改为LinQ-Query会增加性能吗?

Mar*_*ell 5

执行此IMO 的最简单方法是定义一个具有int Id {get;}属性的接口,并让您的类型实现该接口。然后编码到接口。如果您现有的代码是通用的,则您甚至可以添加where T : IYourInterface约束,但可以强制采用IYourInterface任何一种方式(假设T实际上确实实现了该接口)。

如果没有接口:

反思,dynamic两者都有开销;dynamic具有更好的优化(重新使用缓存策略)。

如果你的items列表是强类型到一个特定的T(这里T是这里就不详),那么你可以有可能进一步优化这个概念使用LINQ表达式编译代表:

static class IdFetcher
{
    public static int Fetch<T>(T item) => IdFetcher<T>.Fetch(item);
}
static class IdFetcher<T>
{
    public static int Fetch(T item) => fetch(item);
    static readonly Func<T, int> fetch;
    static IdFetcher()
    {
        var p = Expression.Parameter(typeof(T), "item");
        fetch = Expression.Lambda<Func<T, int>>(
            Expression.PropertyOrField(p, "Id"), p).Compile();
    }
}
Run Code Online (Sandbox Code Playgroud)

然后只需使用IdFetcher<T>.Fetch(obj)IdFetcher.Fetch(obj)(第一个更直接;第二个可用于无法指定的匿名类型T

除此之外:如果您想知道哪个更快:为它们计时(大量迭代)。