次の方法で共有


CA1010: コレクションは、ジェネリック インターフェイスを実装しなければなりません

プロパティ
ルール ID CA1010
Title コレクションは、ジェネリック インターフェイスを実装しなければなりません
[カテゴリ] デザイン
修正が中断ありか中断なしか なし
.NET 9 では既定で有効 いいえ

原因

型では System.Collections.IEnumerable インターフェイスを実装しますが、System.Collections.Generic.IEnumerable<T> インターフェイスは実装しません。また、包含アセンブリのターゲットが .NET になっています。 この規則では、System.Collections.IDictionary を実装する型を無視します。

既定では、この規則の対象は外部から参照できる型のみですが、これは構成可能です。 また、ジェネリック インターフェイスを実装することを求めるように、追加のインターフェイスを構成することもできます。

規則の説明

コレクションの操作性を拡充するために、ジェネリック コレクション インターフェイスの 1 つを実装します。 これにより、コレクションを使用して、次のようなジェネリック コレクション型を設定できます。

違反の修正方法

この規則違反を修正するには、次のジェネリック コレクション インターフェイスのいずれかを実装します。

どのようなときに警告を抑制するか

この規則からの警告は抑制してもかまいません。ただし、コレクションの使用はさらに制限されます。

警告を抑制する

単一の違反を抑制するだけの場合は、ソース ファイルにプリプロセッサ ディレクティブを追加して無効にしてから、規則をもう一度有効にします。

#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()
    {
    }
}

既に解放されているクラスの基底クラスの変更は、既存のコンシューマーに対する重大な変更と見なされます。

関連項目