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

속성
규칙 ID CA1010
타이틀 컬렉션은 제네릭 인터페이스를 구현해야 합니다.
범주 디자인
수정 사항이 주요 변경인지 여부 주요 변경 아님
.NET 8에서 기본적으로 사용 아니요

원인

형식은 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 표면에서만 실행되도록 지정하려면 프로젝트의 .editorconfig 파일에 다음 키-값 쌍을 추가합니다.

dotnet_code_quality.CAXXXX.api_surface = private, internal

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

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

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

  • 인터페이스 이름만(포함하는 형식 또는 네임스페이스와 관계없이 해당 이름의 모든 인터페이스 포함).
  • 기호의 설명서 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()
    {
    }
}

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

참고 항목