9

私は .NET4.5 がもたらす変化について調べていましたが、このブログ投稿で、私が知らなかったり理解できなかったりすることに出くわしました。

読み取り専用コレクションの実装について話すとき、Immo Landwerthは次のように述べています。

残念ながら、私たちの型システムでは、T を入力として受け取るメソッドがない限り、T の型を共変にすることはできません。したがって、IndexOf メソッドを IReadOnlyList に追加することはできません。これは、共分散がサポートされていないことに比べれば小さな犠牲であると考えています。

IReadOnlyList<Shape>私の明らかに限られた理解からすると、 a を渡すことによって を必要とするメソッドを呼び出せるようにするために、メソッドをIReadOnlyList<Circle>持つことはできないと彼は言っているようIReadOnlyList<T>.IndexOf(T someShape)です。

型システムがそれをどのように防ぐのかわかりません。誰か説明できますか?

4

3 に答える 3

11

を実装するとCircleしますIEquatable<Circle>IReadOnlyList<Circle>.IndexOfそれが利用可能であれば、それは自然に使用されます。これを書くことができれば:

IReadOnlyList<Circle> circles = ...;
IReadOnlyList<Shape> shapes = circles;
int index = shapes.IndexOf(new Square(10));

それは、明らかに悪い考えであるaSquareを渡そうとすることになります。Circle.Equals(Circle)

「入力位置に値がない」ことを強制する規則Tは、C# 4 仕様のセクション 13.1.3 にあります。詳細については、一般的な差異に関するEric Lippertのブログ シリーズもお読みください。

于 2012-06-18T12:11:17.300 に答える
6

は共変であるためIReadOnlyList<T>、任意のスーパータイプにキャストできT、すべてのメソッドは引き続き契約に従って機能するはずです。の最もスーパーなスーパータイプTObjectです。IndexOfObject

Jon Skeet が述べているように、Circleオブジェクトのリストで次のように尋ねることができます:Squareこのリスト内の特定のインデックスは何ですか? 唯一の正しい応答は「ここにはありません」であり、IndexOf-1 を返し、例外をスローしない必要があります。

だから、私はジョン・スキートに同意しません。共変のジェネリック パラメーターの制限を考慮しArrayList.indexOf、JavaIndexOfと同様に、BCL チームは次のシグネチャを持つメソッドを含める必要がありました。

int IndexOf(object item);

まったく同じ引数が in に適用さContainsIReadOnlyCollectionます。互換性のない型のオブジェクトを渡すと、コレクションには明らかにそれが含まれず、メソッドは単に を返す必要がありfalseます。

唯一の欠点は値型のボックス化ですが、実際の実装ではIReadOnlyList.IndexOfメソッドが非表示になり、独自のジェネリック オーバーロードが提供されるため、この引数は意味がありません。

IndexOfしたがって、互換性のないオブジェクトがインターフェイス上にある場合、渡されたときに -1 を返すことを期待するのは正しいことです。


M42.Collectionsこれが実際にどのように機能するかを示すために、この原則をライブラリに実装しました。ここからダウンロードできます:

M42 Collections - コレクションを適切に操作するためのポータブル .NET ライブラリ.

于 2013-01-17T01:00:22.987 に答える
1

理論的には (.NET でまだ実装されているかどうかは不明)、次IndexOfのすべてのサブタイプを定義するのが正しいことに注意してTください。

class ReadOnlyList<+T> = { ...
  Int IndexOf<U>(U elem) where T : U { ... }
}

IndexOf(T elem)が明らかに共変ではない理由を確認するのは興味深いことですが、これは次のとおりT2 : T1です。反対に、 がある場合はとを知っているので、そのようなすべてのも持っています。この型は のサブタイプです。IndexOf(T1 elem)IndexOf(T2 elem)IndexOf<U>(U elem) where T1 : UT2 : T1T1 : UT2 : UUIndexOf<U>(U elem) with T2 : U

この発言は、たとえば、Emir、Kennedy、Russo、および Yu による 2006 年の記事Variance and Generalized Constraints for C# Generics で行われています。彼らは、この定義を受け入れる型システムを提示しています。

于 2012-06-24T15:38:00.350 に答える