다음을 통해 공유


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

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

원인

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

규칙 설명

IEnumerable 또는 IEnumerable<> 형식의 컬렉션은 생성될 때 열거를 연기할 수 있습니다. 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 생성되거나 yield 키워드를 사용하여 생성된 경우) 컬렉션을 구체화하여 위반을 해결할 수 있습니다. 그러나 이렇게 하면 추가 메모리가 할당됩니다.

예시:

위반:

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 파일에서 옵션을 설정 IEnumerable 하여 인수를 범위에 열거 enumeration_methods 하는 사용자 지정 메서드를 추가할 수 있습니다.

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

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

기본적으로 인수를 허용하는 IEnumerable 모든 사용자 지정된 메서드는 인수를 열거하지 않는 것으로 간주됩니다. .editorconfigassume_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

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

참고 항목