Share via


CA1851: 컬렉션의 IEnumerable 여러 열거 가능

속성
규칙 ID CA1851
타이틀 컬렉션의 IEnumerable 가능한 여러 열거형
범주 성능
수정 사항이 주요 변경인지 여부 주요 변경 아님
도입된 버전 .NET 7
.NET 8에서 기본적으로 사용 아니요

원인

컬렉션의 여러 열거형이 IEnumerable 검색되었습니다.

규칙 설명

IEnumerable 또는 IEnumerable< T> 형식의 컬렉션은 생성될 때 열거를 연기할 수 있습니다. Select와 같은 많은 LINQ 메서드는 지연된 실행을 사용합니다. 컬렉션이 ElementAt와 같은 LINQ 열거형 메서드로 전달되거나 각 문에 사용되는 경우 열거형이 시작됩니다. 열거형 결과는 한 번 계산되지 않고 Lazy와 같이 캐시됩니다.

열거형 작업 자체가 비용이 많이 드는 경우(예: 데이터베이스에 대한 쿼리) 여러 열거형으로 인해 프로그램의 성능이 저하됩니다.

열거형 작업에 부작용이 있는 경우 여러 열거형으로 인해 버그가 발생할 수 있습니다.

위반 문제를 해결하는 방법

컬렉션의 IEnumerable 기본 형식이 다른 형식인 경우 컬렉션을 기본 형식으로 ListArray변환하여 진단을 수정하는 것이 안전합니다.

위반:

public void MyMethod(IEnumerable<int> input)
{
    var count = input.Count();
    foreach (var i in input) { }
}
Public Sub MyMethod(input As IEnumerable(Of Integer))
    Dim count = input.Count()
    For Each i In input
    Next
End Sub

Fix:

public void MyMethod(IEnumerable<int> input)
{
    // If the underlying type of 'input' is List<int>
    var inputList = (List<int>)input;
    var count = inputList.Count();
    foreach (var i in inputList) { }
}
Public Sub MyMethod(input As IEnumerable(Of Integer))
    ' If the underlying type of 'input' is array
    Dim inputArray = CType(input, Integer())
    Dim count = inputArray.Count()
    For Each i In inputArray
    Next
End Sub

컬렉션의 IEnumerable 기본 형식이 반복기 기반 구현을 사용하는 경우(예: LINQ 메서드에서 생성되는 경우 또는 Select 수율 키워드(keyword) 사용하여 생성되는 경우) 컬렉션을 구체화하여 위반을 해결할 수 있습니다. 그러나 이렇게 하면 추가 메모리가 할당됩니다.

예시:

위반:

public void MyMethod()
{
    var someStrings = GetStrings().Select(i => string.Concat("Hello"));

    // It takes 2 * O(n) to complete 'Count()' and 'Last()' calls, where 'n' is the length of 'someStrings'.
    var count = someStrings.Count();
    var lastElement = someStrings.Last();
}
Public Sub MyMethod()
    Dim someStrings = GetStrings().Select(Function(i) String.Concat(i, "Hello"))

    ' It takes 2 * O(n) to complete 'Count()' and 'Last()' calls, where 'n' is the length of 'someStrings'.
    Dim count = someStrings.Count()
    Dim lastElement = someStrings.Last()
End Sub

Fix:

public void MyMethod()
{
    var someStrings = GetStrings().Select(i => string.Concat("Hello"));
    // Materialize it into an array.
    // Note: This operation would allocate O(n) memory,
    // and it takes O(n) time to finish, where 'n' is the length of 'someStrings'.
    var someStringsArray = someStrings.ToArray()

    // It takes 2 * O(1) to complete 'Count()' and 'Last()' calls.
    var count = someStringsArray.Count();
    var lastElement = someStringsArray.Last();
}
Public Sub MyMethod()
    Dim someStrings = GetStrings().Select(Function(i) String.Concat(i, "Hello"))
    ' Materialize it into an array.
    ' Note: This operation would allocate O(n) memory,
    ' and it takes O(n) time to finish, where 'n' is the length of 'someStrings'.
    Dim someStringsArray = someStrings.ToArray()

    ' It takes 2 * O(1) to complete 'Count()' and 'Last()' calls.
    Dim count = someStrings.Count()
    Dim lastElement = someStrings.Last()
End Sub

사용자 지정된 열거형 메서드 및 LINQ 체인 메서드 구성

기본적으로 네임스페이스의 모든 메서드 System.Linq 는 분석 범위에 포함됩니다. .editorconfig 파일에서 옵션을 설정 enumeration_methods 하여 인수를 범위에 열거 IEnumerable 하는 사용자 지정 메서드를 추가할 수 있습니다.

.editorconfig 파일에서 옵션을 설정 linq_chain_methods 하여 사용자 지정된 LINQ 체인 메서드(즉, 메서드가 인수를 사용하고 IEnumerableIEnumerable 인스턴스를 반환)를 분석 범위에 추가할 수도 있습니다.

메서드 IEnumerable 테이크 매개 변수의 기본 가정 구성

기본적으로 인수를 허용하는 IEnumerable 모든 사용자 지정된 메서드는 인수를 열거하지 않는 것으로 간주됩니다. .editorconfig 파일에서 옵션을 설정 assume_method_enumerates_parameters 하여 이 옵션을 변경할 수 있습니다.

경고를 표시하지 않는 경우

컬렉션의 기본 형식 IEnumerable 이 다른 형식 List 인 경우 또는 Array컬렉션을 사용하는 IEnumerable 메서드가 열거하지 않는 경우 이 경고를 표시하지 않는 것이 안전합니다.

경고 표시 안 함

단일 위반만 표시하지 않으려면 원본 파일에 전처리기 지시문을 추가하여 규칙을 사용하지 않도록 설정한 후 다시 사용하도록 설정합니다.

#pragma warning disable CA1851
// The code that's violating the rule is on this line.
#pragma warning restore CA1851

파일, 폴더 또는 프로젝트에 대한 규칙을 사용하지 않도록 설정하려면 구성 파일에서 심각도를 none으로 설정합니다.

[*.{cs,vb}]
dotnet_diagnostic.CA1851.severity = none

자세한 내용은 방법: 코드 분석 경고 표시 안 함을 참조하세요.

참고 항목