Pregunta

Hola, supongamos que estos 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;              
        }

¿Cuál es más rápido? Cuando miro el primer método, veo que la memoria está asignada para List, que en mi opinión no es necesaria. El método IEnumerable parece ser más rápido para mí.

Por ejemplo, suponga que llama

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

Ahora, otro problema es, ¿hay una diferencia de rendimiento entre estos 2 anteriores?

¿Qué opinas?

¿Fue útil?

Solución

En este caso particular, usar el formulario IEnumerable < T > será más eficiente, porque solo necesita saber el recuento. No tiene sentido almacenar los datos, cambiar el tamaño de los buffers, etc. si no es necesario.

Si necesita volver a utilizar los resultados por cualquier motivo, el formulario List < T > sería más eficiente.

Tenga en cuenta que tanto el método de extensión Count () como la propiedad Count serán eficientes para List < T > como la implementación de < code> Count () comprueba si la secuencia de destino implementa ICollection < T > y usa la propiedad Count si es así.

Otra opción que debería ser incluso más eficiente (aunque solo justo) sería llamar a la sobrecarga de Count que toma un delegado:

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

Eso evitará el nivel adicional de indirecciones incurridas por las cláusulas Where y Select .

(Como dice Marc, para pequeñas cantidades de datos las diferencias de rendimiento probablemente serán insignificantes de todos modos).

Otros consejos

La respuesta precisa a preguntas como esta puede variar dependiendo de muchos factores, y puede cambiar aún más a medida que evoluciona el CLR. La única manera de estar seguro es medirlo, y tener en cuenta que si la diferencia es pequeña en comparación con la operación en la que aparecerá, entonces debe elegir la forma más fácil de leer y mantener.

Y en esa nota, es posible que también desee probar:

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

También puede darse mucha flexibilidad devolviendo IEnumerable < T > y luego utilizando el método de extensión ToList si desea " instantánea " Los resultados en una lista. Esto evitará la evaluación repetida del código para generar la lista, si necesita examinarlo varias veces.

Una parte importante de esta pregunta es "¿qué tan grandes son los datos?" ¿Cuántas filas ...

Para pequeñas cantidades de datos, la lista está bien: llevará un tiempo insignificante asignar una lista lo suficientemente grande, y no cambiará de tamaño muchas veces (ninguna, si puede decirle qué tan grande es por adelantado).

Sin embargo, esto no escala a grandes volúmenes de datos; parece poco probable que su proveedor admita miles de interfaces, por lo que no diría que es necesario ir a este modelo, pero no le hará mucho daño.

Por supuesto, también puedes usar LINQ:

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

Este es también el enfoque de rendimiento diferido bajo las cubiertas ...

La diferencia principal entre IEnumerable e IList:

IEnumerable: Implementa MoveNext, Reset, Get Current Methods y devuelve un tipo de IEnumerator para iterar     A través de registros.

IList: expone la interfaz IEnumerable y también es una colección de objetos no genéricos a los que se puede acceder a través del índice, por lo que IEnumerable + ICollection (manipulación de datos) y agregar, eliminar e insertar (en un índice específico) son útiles. métodos implementados por IList.

Después de mirar su Código en mi opinión, IEnumerable es más eficiente, pero la lista de retorno también es útil si desea realizar alguna manipulación con los datos y si solo desea iterar a través de los datos, entonces IEnumerable es preferible.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top