Question

Bonjour supposons ces deux méthodes:

private List<IObjectProvider> GetProviderForType(Type type)
        {
            List<IObjectProvider> returnValue = new List<IObjectProvider>();

            foreach (KeyValuePair<Type, IObjectProvider> provider in _objectProviders)
            {
                if ((provider.Key.IsAssignableFrom(type) ||
                    type.IsAssignableFrom(provider.Key)) &&
                    provider.Value.SupportsType(type))
                {
                    returnValue.Add(provider.Value);
                }
            }
            return returnValue;
        }

private IEnumerable<IObjectProvider> GetProviderForType1(Type type)
        {
            foreach (KeyValuePair<Type, IObjectProvider> provider in _objectProviders)
                if ((provider.Key.IsAssignableFrom(type) ||
                    type.IsAssignableFrom(provider.Key)) &&
                    provider.Value.SupportsType(type))

                    yield return provider.Value;              
        }

Lequel est le plus rapide? Quand je regarde la première méthode, je vois que la mémoire est allouée pour List, ce qui à mon avis n'est pas nécessaire. La méthode IEnumerable semble être plus rapide.

Par exemple, supposez que vous appeliez

int a = GetProviderForType(myType).Count;
int b = GetProviderForType1(myType).Count();

Maintenant, un autre problème est de savoir s'il y a une différence de performance entre ces 2 précédents.

Qu'en pensez-vous?

Était-ce utile?

La solution

Dans ce cas particulier, l'utilisation du formulaire IEnumerable < T > sera plus efficace, car vous seulement devez connaître le nombre. Il ne sert à rien de stocker les données, de redimensionner les tampons, etc. si vous n'en avez pas besoin.

Si vous deviez utiliser les résultats à nouveau pour une raison quelconque, le formulaire Liste < T > serait plus efficace.

Notez que la méthode d'extension Count () et la propriété Count seront efficaces pour List < T > en tant qu'implémentation de < code> Count () vérifie si la séquence cible implémente ICollection < T > et utilise la propriété Count si c'est le cas.

Une autre option qui devrait être encore plus efficace (bien que juste) serait d'appeler la surcharge de Count qui prend un délégué:

private int GetProviderCount(Type type)
{
  return _objectProviders.Count(provider =>
      (provider.Key.IsAssignableFrom(type) 
       || type.IsAssignableFrom(provider.Key))
      && provider.Value.SupportsType(type));
}

Cela évitera le niveau supplémentaire de dommages indirects engendrés par les clauses Where et Select .

(Comme le dit Marc, pour de petites quantités de données, les différences de performance seront probablement négligeables de toute façon.)

Autres conseils

La réponse précise à des questions comme celle-ci peut varier en fonction de nombreux facteurs et peut évoluer à mesure que le CLR évolue. Le seul moyen d’en être sûr est de le mesurer - et gardez à l’esprit que si la différence est petite par rapport à l’opération dans laquelle elle apparaîtra, vous devez choisir la manière la plus lisible et la plus maintenable de l’écrire.

Et sur cette note, vous pouvez également essayer:

private IEnumerable<IObjectProvider> GetProviderForType1(Type type)
{
    return _objectProviders.Where(provider => 
                  provider.Key.IsAssignableFrom(type) ||
                  type.IsAssignableFrom(provider.Key)) &&
                  provider.Value.SupportsType(type))
                           .Select(p => p.Value);
}

Vous pouvez également vous donner beaucoup de flexibilité en renvoyant IEnumerable < T > , puis en utilisant la méthode d'extension ToList si vous souhaitez "prendre une photo". les résultats dans une liste. Cela évitera une évaluation répétée du code pour générer la liste, si vous devez l'examiner plusieurs fois.

Une partie importante de cette question est "quelle est la taille des données"? Combien de lignes ...

Pour les petites quantités de données, la liste est correcte - il faudra un temps négligeable pour allouer une liste assez grande et elle ne sera pas redimensionnée plusieurs fois (aucune, si vous pouvez indiquer sa taille à l'avance).

Toutefois, cela ne s'adapte pas à d'énormes volumes de données; il semble peu probable que votre fournisseur prenne en charge des milliers d'interfaces. Je ne dirais donc pas qu'il est nécessaire de passer à ce modèle - mais cela ne fera pas très mal.

Bien sûr, vous pouvez également utiliser LINQ:

return from provider in _objectProviders
       where provider.Key.IsAssignableFrom(type) ...
       select provider.Value;

C’est également l’approche rendement différée sous les couvertures ...

La principale différence entre IEnumerable et IList:

IEnumerable: Implémente MoveNext, Reset, Obtient les méthodes en cours et renvoie un type d'IEnumerator à itérer     À travers les enregistrements.

IList: expose l'interface IEnumerable ainsi qu'un ensemble d'objets non génériques accessibles via un index. IEnumerable + ICollection (manipulation des données) et l'ajout, la suppression, l'insertion (à un index spécifique) sont utiles méthodes implémentées par IList.

Après avoir examiné votre code dans My Opinion, IEnumerable est plus efficace, mais renvoyer une liste est également utile si vous souhaitez manipuler des données et si vous souhaitez simplement parcourir des données, alors IEnumerable est préférable.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top