6 votes

Dynamique de performance vs Reflection

J'ai les possibilités suivantes pour récupérer des valeurs dans une liste :

en utilisant la réflexion :

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

en utilisant la dynamique :

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

Les deux boucles font la même chose. Elles filtrent l'IEnumerable (ou la liste) par Field[fieldName] qui peuvent être de différents types mais qui contiennent tous une propriété int appelée "Id".

Je me demande lequel des deux aurait les meilleures performances. En outre : Le fait de changer l'une d'entre elles pour une LinQ-Query augmenterait-il les performances ?

5voto

Marc Gravell Points 482669

El le plus facile La meilleure façon de procéder, selon l'OMI, est de définir une interface qui a une int Id {get;} et faites en sorte que vos types l'implémentent. Ensuite, codez en fonction de l'interface. Si votre code existant est générique, vous pouvez même ajouter une propriété de type where T : IYourInterface mais vous pouvez effectuer un moulage en IYourInterface dans les deux cas (en supposant que T implémente effectivement l'interface).

Si les interfaces ne sont pas une option :

Réflexion et dynamic Les deux ont des frais généraux ; dynamic a une meilleure optimisation (réutilisation d'une stratégie mise en cache).

Si votre items est fortement typée à une liste spécifique T (où T est inconnu ici), alors vous pouvez éventuellement optimiser davantage ce concept en utilisant des expressions LINQ pour compiler les délégués :

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

Il suffit alors d'utiliser IdFetcher<T>.Fetch(obj) o IdFetcher.Fetch(obj) (la première est plus directe ; la seconde est utile pour les types anonymes pour lesquels vous ne pouvez pas spécifier l'attribut T )

Sinon, si vous voulez savoir lequel est le plus rapide, chronométrez-les (pour un grand nombre d'itérations).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X