性能动态 vs 反射

6

我可以通过以下方式获取列表中的值:

使用反射:

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);
   }
}

使用dynamic关键字:

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

这两个循环的作用相同。它们通过Field[fieldName]筛选IEnumerable(或List),该字段可以是不同类型,但它们都包含名为"Id"的int属性。

我想知道哪一个性能更好。 此外:将其中一个更改为LinQ查询是否会提高性能?


1
dynamic 也使用反射,但不像你在第一个示例中那样粗糙。因此,我认为在这里使用 dynamic 会更快。当然,你也可以自己测量一下。 - Evk
2
有一种更简单的方法来处理这种场景 - 添加一个 interface IHasId { int Id {get; } } ,并让你的类型实现它(通常只需要在每个类型中添加 : IHasId,因为隐式接口实现)... 然后使用 foreach(IHasId item in items) { if (item.Id == searchValue) { ...} } - Marc Gravell
1
为什么不在足够大的集合上尝试一下呢?可以使用 StopWatch 进行简单的 测量。同时也要注意不要进行过早优化。还可以参考 https://dev59.com/XW445IYBdhLWcg3w5OII。 - MakePeaceGreatAgain
1个回答

5

在我看来,最简单的方法是定义一个接口,该接口具有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();
    }
}

那么只需使用IdFetcher<T>.Fetch(obj)IdFetcher.Fetch(obj)(第一个更为直接;第二个对于无法指定T的匿名类型很有用)

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接