CA1010: 컬렉션은 제네릭 인터페이스를 구현해야 합니다.

속성 값
규칙 ID CA1010
제목 컬렉션은 제네릭 인터페이스를 구현해야 합니다.
범주 디자인
수정 사항이 호환성을 깨뜨리는지 여부 또는 무중단인지 여부 주요 변경 아님
.NET 10에서 기본적으로 사용하도록 설정 아니요
적용 가능한 언어 C# 및 Visual Basic

원인

형식은 System.Collections.IEnumerable인터페이스를 구현하지만 System.Collections.Generic.IEnumerable<T> 인터페이스를 구현하지 않으며 포함하는 어셈블리는 .NET을 대상으로 합니다. 이 규칙은 System.Collections.IDictionary를 구현하는 형식을 무시합니다.

기본적으로 이 규칙은 외부에 표시되는 형식만 확인하지만 이는 구성 가능합니다. 제네릭 인터페이스 구현을 요구하도록 추가 인터페이스를 구성할 수도 있습니다.

규칙 설명

컬렉션의 유용성을 높이려면 제네릭 컬렉션 인터페이스 중 하나를 구현합니다. 그러면 컬렉션을 사용하여 다음과 같은 제네릭 컬렉션 형식을 채울 수 있습니다.

위반 문제를 해결하는 방법

이 규칙 위반 문제를 해결하려면 다음 제네릭 컬렉션 인터페이스 중 하나를 구현합니다.

경고를 표시하지 않는 경우

이 규칙에서 경고를 억제해도 안전합니다. 그러나 컬렉션의 사용은 더 제한적일 것입니다.

경고 표시 안 함

단일 위반을 억제하려면 원본 파일에 전처리기 지시문을 추가하여 규칙을 비활성화한 후 다시 활성화하십시오.

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

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

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

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

분석할 코드 구성

다음 옵션을 사용하여 이 규칙이 실행될 코드베이스 부분을 구성합니다.

이 규칙, 적용되는 모든 규칙 또는 적용되는 이 범주의 모든 규칙(디자인)에 대해 이러한 옵션을 구성할 수 있습니다. 자세한 내용은 코드 품질 규칙 구성 옵션을 참조하세요.

특정 API 화면 포함

api_surface 옵션을 설정하여 접근성에 따라 이 규칙을 실행할 코드베이스의 일부를 구성할 수 있습니다. 예를 들어 규칙이 퍼블릭이 아닌 API 표면에서만 실행되도록 지정하려면 프로젝트의 .editorconfig 파일에 다음 키-값 쌍을 추가합니다.

dotnet_code_quality.CAXXXX.api_surface = private, internal

메모

XXXX CAXXXX 부분을 해당 규칙의 ID로 바꿉니다.

추가 필수 제네릭 인터페이스

|로 구분된 인터페이스 이름 목록을 ->로 구분된 필수 제네릭 정규화된 인터페이스로 구성할 수 있습니다.

허용되는 인터페이스 형식:

  • 인터페이스 이름만(포함하는 형식 또는 네임스페이스와 관계없이 해당 이름의 모든 인터페이스 포함).
  • 기호의 설명서 ID 형식에서 선택적으로 T: 접두사를 포함할 수 있는 완전 수식 이름.

예:

옵션 값 요약
dotnet_code_quality.CA1010.additional_required_generic_interfaces = ISomething->System.Collections.Generic.IEnumerable`1 네임스페이스와 관계없이 ISomething을 구현하는 모든 형식은 System.Collections.Generic.IEnumerable<T>도 구현해야 합니다.
dotnet_code_quality.CA1010.additional_required_generic_interfaces = T:System.Collections.IDictionary->T:System.Collections.Generic.IDictionary`2 System.Collections.IDictionary를 구현하는 모든 형식은 System.Collections.Generic.IDictionary<TKey,TValue>도 구현되어야 합니다.

예시

다음 예제에서는 제네릭이 아닌 CollectionBase 클래스에서 파생되고 이 규칙을 위반하는 클래스를 보여 줍니다.

public class Book
{
    public Book()
    {
    }
}

public class BookCollection : CollectionBase
{
    public BookCollection()
    {
    }

    public void Add(Book value)
    {
        InnerList.Add(value);
    }

    public void Remove(Book value)
    {
        InnerList.Remove(value);
    }

    public void Insert(int index, Book value)
    {
        InnerList.Insert(index, value);
    }

    public Book? this[int index]
    {
        get { return (Book?)InnerList[index]; }
        set { InnerList[index] = value; }
    }

    public bool Contains(Book value)
    {
        return InnerList.Contains(value);
    }

    public int IndexOf(Book value)
    {
        return InnerList.IndexOf(value);
    }

    public void CopyTo(Book[] array, int arrayIndex)
    {
        InnerList.CopyTo(array, arrayIndex);
    }
}

이 규칙 위반 문제를 해결하려면 다음 중 하나를 수행합니다.

인터페이스 구현으로 수정

다음 예제에서는 IEnumerable<T>, ICollection<T>, IList<T> 제네릭 인터페이스를 구현하여 위반을 수정합니다.

public class Book
{
    public Book()
    {
    }
}

public class BookCollection : CollectionBase, IList<Book?>
{
    public BookCollection()
    {
    }

    int IList<Book?>.IndexOf(Book? item)
    {
        return this.List.IndexOf(item);
    }

    void IList<Book?>.Insert(int location, Book? item)
    {
    }

    Book? IList<Book?>.this[int index]
    {
        get => (Book?)this.List[index];
        set { }
    }

    void ICollection<Book?>.Add(Book? item)
    {
    }

    bool ICollection<Book?>.Contains(Book? item)
    {
        return true;
    }

    void ICollection<Book?>.CopyTo(Book?[] array, int arrayIndex)
    {
    }

    bool ICollection<Book?>.IsReadOnly
    {
        get { return false; }
    }

    bool ICollection<Book?>.Remove(Book? item)
    {
        if (InnerList.Contains(item))
        {
            InnerList.Remove(item);
            return true;
        }
        return false;
    }

    IEnumerator<Book> IEnumerable<Book?>.GetEnumerator()
    {
        return new BookCollectionEnumerator(InnerList.GetEnumerator());
    }

    private class BookCollectionEnumerator : IEnumerator<Book>
    {
        private IEnumerator _Enumerator;

        public BookCollectionEnumerator(IEnumerator enumerator)
        {
            _Enumerator = enumerator;
        }

        public Book Current
        {
            get { return (Book)_Enumerator.Current; }
        }

        object IEnumerator.Current
        {
            get { return _Enumerator.Current; }
        }

        public bool MoveNext()
        {
            return _Enumerator.MoveNext();
        }

        public void Reset()
        {
            _Enumerator.Reset();
        }

        public void Dispose()
        {
        }
    }
}

기본 클래스 변경으로 수정

다음 예제에서는 컬렉션의 기본 클래스를 제네릭이 아닌 CollectionBase 클래스에서 제네릭 Collection<T>(Visual Basic에서 Collection(Of T)) 클래스로 변경하여 위반을 수정합니다.

public class Book
{
    public Book()
    {
    }
}

public class BookCollection : Collection<Book>
{
    public BookCollection()
    {
    }
}

이미 릴리스된 클래스의 기본 클래스를 변경하는 것은 기존 소비자의 호환성이 손상되는 변경으로 간주됩니다.

참고하기