Pergunta

Hi supõem estes 2 métodos:

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

Qual deles é mais rápido? Quando eu olho para o primeiro método, vejo que a memória é alocada para a lista, o que na minha opinião não é necessário. O IEnumerable método parece ser mais rápido para mim.

Por exemplo, suponha que você chamar

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

Agora, outra questão é, existe uma diferença de desempenho entre estes 2 acima?

O que você acha?

Foi útil?

Solução

Neste caso particular, utilizando o formulário IEnumerable<T> será mais eficiente, porque você única necessidade de saber a contagem. Não há nenhum ponto em armazenar os dados, redimensionamento buffers etc, se você não precisa.

Se você precisava usar os resultados novamente por qualquer motivo, a forma List<T> seria mais eficiente.

Note que tanto o método de extensão Count() ea propriedade Count será eficiente para List<T> como a implementação de cheques Count() para ver se os instrumentos de sequências-alvo ICollection<T> e usa a propriedade Count se assim for.

Outra opção que deve ser mesmo mais eficiente (embora só agora) seria chamar a sobrecarga de Count que leva um delegado:

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

Isso vai evitar o nível extra de indireções incorridos pelas cláusulas Where e Select.

(Como Marc diz, para pequenas quantidades de dados as diferenças de desempenho provavelmente será de qualquer maneira insignificante.)

Outras dicas

A resposta precisa a perguntas como esta pode variar dependendo de uma série de fatores, e pode mudar ainda mais com a evolução CLR. A única maneira de ter certeza é medi-la -. E ter em mente que, se a diferença é pequena em comparação com a operação deste aparecerão na, então você deve escolher a forma mais legível, de fácil manutenção de escrevê-lo

E nessa nota, que você pode também querer tentar:

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

Você também pode dar-se muita flexibilidade, retornando IEnumerable<T> e, em seguida, usando o método de extensão ToList se você quiser "instantâneo" os resultados em uma lista. Isso irá evitar a avaliação repetida do código para gerar a lista, se você precisa examiná-lo várias vezes.

Uma parte importante desta questão é "quão grande são os dados"? Quantas linhas ...

Para pequenas quantidades de dados, a lista é muito bem - isso vai levar tempo insignificante para alocar uma lista grande o suficiente, e que não irá redimensionar muitas vezes (nenhum, se você pode dizer como é grande para ser com antecedência) <. / p>

No entanto, isso não escala a grandes volumes de dados; parece improvável que o seu provedor suporta milhares de interfaces de, então eu não diria que é necessário para ir para este modelo -. mas não irá prejudicar imensamente

É claro, você pode usar LINQ, também:

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

Esta é também a abordagem yield diferido sob o cobre ...

A principal diferença entre IEnumerable e IList:

IEnumerable: Implementos MoveNext, Reset, Get Métodos atual e retorna um tipo de IEnumerator para iterar Através Records.

IList: expõe a interface IEnumerable, assim como também é uma coleção de objetos não genéricos que pode acessado através índice para IEnumerable + ICollection (manipulação de dados) e adicionar, remover, Insert (pelo índice específico) são úteis métodos implementados por IList.

Depois de olhar para o seu código em minha opinião IEnumerable é mais eficiente, mas a lista de retornar também é útil se você quiser fazer alguma manipulação com os dados e se você quiser apenas para percorrer os dados, em seguida, IEnumerable é preferível.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top