Domanda

Ciao supponiamo che questi 2 metodi:

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

Quale è più veloce? Quando guardo il primo metodo, vedo che la memoria è allocata per List, ciò che secondo me non è necessario. Il metodo IEnumerable sembra essere più veloce per me.

Ad esempio, supponi di chiamare

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

Ora, un altro problema è, c'è una differenza di prestazioni tra questi 2 sopra?

Cosa ne pensi?

È stato utile?

Soluzione

In questo caso particolare, l'utilizzo del modulo IEnumerable < T > sarà più efficiente, poiché solo è necessario conoscere il conteggio. Non ha senso archiviare i dati, ridimensionare i buffer, ecc., Se non è necessario.

Se fosse necessario utilizzare nuovamente i risultati per qualsiasi motivo, il modulo Elenco < T > sarebbe più efficiente.

Nota che sia il metodo di estensione Count () che la proprietà Count saranno efficienti per List < T > come implementazione di < code> Count () verifica se la sequenza target implementa ICollection < T > e, in tal caso, utilizza la proprietà Count .

Un'altra opzione che dovrebbe essere più efficiente (anche se solo giusta) sarebbe quella di chiamare il sovraccarico di Count che accetta un delegato:

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

Ciò eviterà il livello extra di indicazioni indirette sostenute dalle clausole Where e Select .

(Come dice Marc, per piccole quantità di dati le differenze di prestazioni saranno probabilmente comunque trascurabili.)

Altri suggerimenti

La risposta precisa a domande come questa può variare a seconda di molti fattori e può cambiare ulteriormente con l'evoluzione del CLR. L'unico modo per essere sicuri è misurarlo - e tieni presente che se la differenza è piccola rispetto all'operazione in cui apparirà, dovresti scegliere il modo più leggibile e sostenibile di scriverlo.

E su quella nota, potresti anche provare:

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

Puoi anche darti molta flessibilità restituendo IEnumerable < T > e quindi usando il metodo di estensione ToList se vuoi " snapshot " i risultati in un elenco. Ciò eviterà una valutazione ripetuta del codice per generare l'elenco, se è necessario esaminarlo più volte.

Una parte importante di questa domanda è "quanto sono grandi i dati"? Quante righe ...

Per piccole quantità di dati, l'elenco va bene - ci vorrà un tempo trascurabile per allocare un elenco abbastanza grande, e non si ridimensionerà molte volte (nessuno, se si può dire quanto sia grande in anticipo).

Tuttavia, questo non si adatta a enormi volumi di dati; sembra improbabile che il tuo provider supporti migliaia di interfacce, quindi non direi che necessario andare a questo modello - ma non farà molto male.

Ovviamente puoi usare anche LINQ:

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

Questo è anche l'approccio differito rendimento sotto le copertine ...

La principale differenza tra IEnumerable e IList:

IEnumerable: Implementa MoveNext, Reimposta, Ottieni metodi correnti e restituisce un tipo di IEnumerator da Iterate     Attraverso la documentazione.

IList: espone l'interfaccia IEnumerable e anche una raccolta di oggetti non generici a cui è possibile accedere tramite l'indice, quindi IEnumerable + ICollection (Manipolazione dei dati) e aggiungere, rimuovere, inserire (in un indice specifico) sono utili metodi implementati da IList.

Dopo aver esaminato il tuo codice a mio parere, IEnumerable è più efficiente ma l'elenco di ritorno è utile anche se vuoi manipolare i dati e se vuoi semplicemente scorrere i dati, è preferibile IEnumerable.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top