6

I have the following possibilities to retrieve values in a list:

using reflection:

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

using dynamic:

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

Both loops do the same. They filter the IEnumerable (or List) by Field[fieldName] which can be of different types but which all contain a int-property called "Id".

I wonder, which one would have a better performance. In addition: Would changing one of those to a LinQ-Query increase the performance?

Ole Albers
  • 8,715
  • 10
  • 73
  • 166
  • 1
    `dynamic` also uses reflection, but not in such a crude way you do in your first example. So I'd suspect dynamic will be faster here. Of course you could have just measured that yourself. – Evk Dec 07 '17 at 10:07
  • 2
    there's a much simpler way to approach this kind of scennario - add an `interface IHasId { int Id {get; } }` and have your types implement it (which because of implicit interface implementations usually just means adding `: IHasId` to each)... then `foreach(IHasId item in items) { if (item.Id == searchValue) { ...} }` – Marc Gravell Dec 07 '17 at 10:08
  • 1
    Why don´t you simply try it out on a big enough collection? Simply *measure* it, e.g. using `StopWatch`. And also have in mind not to do [premature optimization](http://wiki.c2.com/?PrematureOptimization). Also have a look at https://stackoverflow.com/questions/4646786/dynamic-lang-runtime-vs-reflection. – MakePeaceGreatAgain Dec 07 '17 at 10:09

1 Answers1

5

The easiest way to do this IMO is to define an interface that has an int Id {get;} property and have your types implement it. Then code to the interface. If your existing code is generic you might even be able to add awhere T : IYourInterface constraint, but you can cast to IYourInterface either way (assuming T actually does implement the interface).

If interfaces aren't an option:

Reflection and dynamic both have overheads; dynamic has better optimization (re-using a cached strategy).

If your items list is strongly typed to a specific T (where T is unknown here), then you can possibly further optimize this concept using LINQ expressions to compile delegates:

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

Then just use IdFetcher<T>.Fetch(obj) or IdFetcher.Fetch(obj) (the first is more direct; the second is useful for anonymous types where you can't specify the T)

Other than that: if you want to know which is faster: time them (for large numbers of iterations).

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900