C# List<T> 및 IEnumerable<T> 성능 질문
-
06-07-2019 - |
문제
안녕하세요, 다음 두 가지 방법을 가정해 보겠습니다.
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;
}
어느 것이 더 빠르나요?첫 번째 방법을 보면 List에 메모리가 할당되어 있는데 제 생각에는 필요하지 않은 것 같습니다.그만큼 IEnumerable 나에게는 방법이 더 빠른 것 같다.
예를 들어, 전화를 걸었다고 가정해 보겠습니다.
int a = GetProviderForType(myType).Count;
int b = GetProviderForType1(myType).Count();
이제 또 다른 문제는 위의 두 가지 사이에 성능 차이가 있습니까?
어떻게 생각하나요?
해결책
이 특별한 경우에는 IEnumerable<T>
양식을 작성하는 것이 더 효율적일 것입니다. 오직 수를 알아야 합니다.필요하지 않은 경우 데이터를 저장하고 버퍼 크기를 조정하는 등의 작업은 의미가 없습니다.
어떤 이유로든 결과를 다시 사용해야 하는 경우 List<T>
형태가 더 효율적일 것입니다.
두 가지 모두 Count()
확장 방법과 Count
부동산은 효율적일 것입니다 List<T>
구현으로 Count()
대상 시퀀스가 구현되는지 확인합니다. ICollection<T>
그리고 Count
그렇다면 재산.
균등해야 하는 또 다른 옵션 더 효율적이지만 (비록 단지) Count
대리인이 필요합니다.
private int GetProviderCount(Type type)
{
return _objectProviders.Count(provider =>
(provider.Key.IsAssignableFrom(type)
|| type.IsAssignableFrom(provider.Key))
&& provider.Value.SupportsType(type));
}
그러면 다음과 같은 추가 수준의 간접 참조가 방지됩니다. Where
그리고 Select
조항.
(Marc가 말했듯이, 적은 양의 데이터의 경우 성능 차이는 어쨌든 무시할 수 있을 것입니다.)
다른 팁
이와 같은 질문에 대한 정확한 답변은 많은 요인에 따라 다를 수 있으며 CLR이 진화함에 따라 더 변화 될 수 있습니다. 확실하게하는 유일한 방법은 그것을 측정하는 것입니다. 그리고 차이가 작전에 비해 작은 경우, 이것이 가장 읽기 쉬운 유지 관리 가능한 방법을 선택해야한다는 것을 명심하십시오.
그리고 그 메모에서, 당신은 또한 시도하고 싶을 수도 있습니다.
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);
}
당신은 또한 돌아와서 많은 유연성을 줄 수 있습니다. IEnumerable<T>
그리고 사용합니다 ToList
확장 메소드 결과를 목록에 "스냅 샷"하려면. 이렇게하면 여러 번 검사 해야하는 경우 목록을 생성하기위한 코드의 반복적 인 평가를 피할 수 있습니다.
이 질문의 중요한 부분은 "데이터가 얼마나 큽니까?"입니다. 얼마나 많은 행 ...
소량의 데이터의 경우 목록이 괜찮습니다. 큰 목록을 할당하는 데 무시할만한 시간이 걸리며 여러 번 크기를 조정하지 않습니다 (미리 미리 얼마나 큰지 알 수 있다면).
그러나 이것은 막대한 데이터 볼륨으로 확장되지 않습니다. 귀하의 공급자가 수천 개의 인터페이스를 지원할 가능성은 거의 없으므로 필요한 이 모델로 이동하려면 - 그러나 그것은 크게 아프지 않을 것입니다.
물론 LINQ도 사용할 수 있습니다.
return from provider in _objectProviders
where provider.Key.IsAssignableFrom(type) ...
select provider.Value;
이것은 또한 연기입니다 yield
표지 아래에 접근하는 ...
ienumerable과 ilist의 주요 차이점 :
ienumerable : movenext를 구현하고, 재설정하고, 현재 메소드를 가져오고, Ienumerator 유형을 반환하여 레코드를 반복합니다.
ILIST : Ienumerable 인터페이스를 노출시켜 색인을 통해 액세스 할 수있는 비 영진 객체 모음이므로 Ienumerable+icollection (데이터 조작) 및 추가, 제거, 삽입 (특정 색인)이 구현 한 유용한 방법입니다. 일리스트.
내 의견으로는 코드를 살펴본 후 ienumerable이 더 효율적이지만 데이터를 사용하여 약간의 조작을하고 싶다면 데이터를 반복하려면 ienumerable이 바람직합니다.