Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Performance dynamic vs Reflection

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?

like image 600
Ole Albers Avatar asked Dec 07 '17 10:12

Ole Albers


People also ask

How do I reflect over the members of dynamic object?

dynamic obj = new SampleObject(); Console. WriteLine(obj. SampleProperty); //Prints "SampleProperty". So, you don't have anything to reflect over - this object doesn't have any properties, and at the same time all valid property names will work.

Is C# reflection slow?

Reflection is not THAT slow. Invoking a method by reflection is about 3 times slower than the normal way. That is no problem if you do this just once or in non-critical situations. If you use it 10'000 times in a time-critical method, I would consider to change the implementation.

When to use reflection in c#?

You can use reflection to dynamically create an instance of a type, bind the type to an existing object, or get the type from an existing object and invoke its methods or access its fields and properties. If you are using attributes in your code, reflection enables you to access them.


1 Answers

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).

like image 149
Marc Gravell Avatar answered Sep 28 '22 07:09

Marc Gravell