5

ただ好奇心が強いです。確かに、ジェネリックスの型推論の一般的なケースは決定不可能であることは誰もが知っています。したがって、C#はいかなる種類のサブタイピングも行いません。Foo<T>がジェネリックである場合、Foo<int>Foo<T>Foo <Object> 、またはその他のサブタイプではありません。調理します。そして確かに、私たちは皆、醜いインターフェースや抽象クラス定義でこれをハックしています。

しかし...一般的な問題に打ち勝つことができない場合は、解決策を簡単なケースに限定してみませんか。たとえば、上記の私のリストでは、Foo<int>がFoo<T>のサブタイプであることは明らかであり、確認するのは簡単です。Foo<Object>に対するチェックについても同じです。

それで、もし彼らがただ言うなら、深淵から忍び寄るであろう他のいくつかの深い恐怖があります、aw shucks、私たちは私たちができることをしますか?それとも、これはマイクロソフトの言語担当者の側のある種の宗教的な純粋さですか?


アップデート:

これは非常に古いスレッドです。最近、C#にはvarがあり、これは私が不満を言ったことの半分を解決します。次に、匿名のデリゲートのLinqスタイルを使用すると、同じものを2回入力する必要がないという優れた表記法があります。したがって、私が反対していたことのすべての側面は、C#の最近の変更によって解決されました(または、スレッドを投稿したときに紹介されたばかりのことを学ぶのに時間がかかっただけです...)私はこれらの新しいものを使用します信頼性の高いクラウドコンピューティング(isis2.codeplex.com)用のIsis2システムの機能があり、その結果、ライブラリのルックアンドフィールは非常にクリーンになっていると思います。それをチェックして、あなたの考えを教えてください)。-ケン・バーマン(2014年7月)

4

6 に答える 6

7

彼らはすでに多くの「簡単な」ケースでそれを解決しています。C#4.0は、インターフェイスとデリゲートのジェネリック型パラメーターの共変性と反変性をサポートしています。しかし、残念ながらクラスではありません。

この制限を回避するのはかなり簡単です。

List<Foo> foos = bars.Select(bar => (Foo)bar).ToList();
于 2010-12-21T20:33:30.747 に答える
5

Foo<int>のサブタイプであるのはOBVIOUSですFoo<T>

多分あなたには、しかし私にはではありません。

私にとって、これが型システムに食い込む大きな穴は、単に受け入れられません。そのようなウィンドウの外に型安全性を捨てたいのなら、私はむしろこのようなもののために実際に設計された動的に型付けされた言語を使用したいと思います。

配列が共変であるという事実は、これが型安全性を破ることが知られているとしても、十分に悪いことです。今、あなたはすべてのためにそれを破りたいですか?

これは、型システムが何であるかということの核心になります。型システムが行うのは、プログラムを拒否することだけです。そしてライスの定理のために、それらの拒否されたプログラムには、完全にタイプされた、タイプセーフなプログラムが含まれています。

それは莫大な費用です。表現度を奪い、有用なプログラムを書くことを妨げます。そのコストを正当化するために、型システムは大きな時間を返済する方が良いです。それを行うには、基本的に2つの方法があります。プログラムレベルで取り除いたタイプレベルでの表現度の還元と、タイプの安全性です。

前者は、C#の型システムが、リモートで興味深いものを表現するのに十分なほど強力ではないという理由だけで、リリースされました。nullこれは後者のみを残し、共変配列、無制限の副作用などのために、すでにかなり不安定なunsafe状況にあります。ジェネリック型を自動的に共変にすることで、残っている型安全性の最後の断片を多かれ少なかれ完全に取り除くことができます。

実際にタイプセーフであるケースはごくわずかです。S <: T ⇒ G<S> <: G<T>(そのような例の1つです。)そして、タイプセーフIEnumerableであるだけの場合もおそらく同じくらい多くあります。S <: T ⇒ G<T> <: G<S>IObservable、、、、。)一般に、タイプIComparerセーフでもタイプセーフでありません。IComparableIEqualityComparer G<S> <: G<T>G<T> <: G<S>

于 2010-12-21T21:04:17.537 に答える
2

重要なのは、すべての場合にそれを行うことはできないので、どの場合にもそれを行わないということです。どこに線を引くかが問題です。C#を使用するすべての人がそれを行わないことを知っているよりも、あなたがそれを行わない場合。あなたがそれを時間の一部で行うならば、それはそれが複雑になるときです。これは、コードがどのように動作するかについての推測ゲームになる可能性があります。プログラマーにとって複雑になり、コードでエラーを引き起こす可能性があるのは、簡単なこととそうでないことのすべてのエッジケースです。

これは絶対に大混乱を引き起こすシナリオです。シナリオAでブーイングがバーであると推測できるとしましょう。他の誰かが来て基本タイプの一部を変更しましたが、これはもはや当てはまりません。常に適用するか、決して適用しないようにすることで、このような状況に遭遇することはありません。複雑な環境では、このような問題を追跡することは絶対的な悪夢になる可能性があります。特に、これを考慮に入れると、コンパイル時にキャッチできない場合があります(リフレクション、DLRなど)。変換を手動で処理するコードを作成する方が、将来的には機能しない可能性がある場合にシナリオで機能すると想定するよりもはるかに簡単です(新しいバージョンへのアップグレードはカウントされません)。

C#4.0は、プログラマーにとって「安全」であると感じたものを推測できるため、この一部を修正します。

于 2010-12-21T20:33:39.250 に答える
0

特別な場合に必要以上に泥だらけになり、複雑になっている言語の実際の良い例は英語です。プログラミング言語では、「cの後を除いてeの前にi」のようなものは、言語を使いにくくし、そのため、あまり有用ではありません。

于 2010-12-21T20:50:40.333 に答える
0

ジェネリッククラスのインスタンスは異なるメソッドシグネチャを持っているので、私は信じていません。特定のクラスが基本クラスから継承されていると見なすのは意味がありません。

class Base<T> 
{
 public T Method() { return default(T);}
}

BaseとBaseの両方が同じシグネチャ(基本クラスからのもの)を持つ「メソッド」を持っていることを提案した場合、基本クラスへの参照を使用して呼び出すことができます。基本クラスを指している、Base<int>または指している場合に、システムで「メソッド」がどのような明らかな戻り値を示すかを説明してください。Base<string>

于 2010-12-22T04:24:24.880 に答える
0

それで、私は私の本当の問題に対するエレガントな回避策を見つけました(C#が過度に制約していることはわかりますが)。

あなたが集めたように、私の主な目標は、後で(たとえば2011年に)作成するメソッドへのコールバックを登録でき、現在は存在しないジェネリック型パラメーターを使用して外部で定義されたコードを作成することです。したがって、私がライブラリを書いた時点(今日)では利用できません。

たとえば、来年定義するオブジェクトのリストを作成し、リストの要素を繰り返し処理して、各オブジェクトの「Aggregate <KeyType、ValueType>」メソッドを呼び出す必要があります。私のフラストレーションは、クラスまたはクラス内のオブジェクトを確実に登録できる一方で、型がわからないため、C#型チェックではメソッドを呼び出せなかったことです(GetType()を介して型を取得できますが、それらを式の型として使用しないでください)。そのため、リフレクションを使用して目的の動作を手動でコンパイルし始めました。これは醜く、型の安全性に違反する可能性があります。

そして答えは...匿名のクラスです。匿名クラスはクロージャのようなものなので、「register」ルーチン内でコールバックを定義できます(タイプにアクセスできます。オブジェクトを登録するときにそれらを渡すことができます)。少し匿名のコールバックメソッドをインラインで作成し、それにデリゲートを保存します。C#はアグリゲーターがパラメーターの種類を「知っている」と見なすため、コールバックメソッドはアグリゲーターを呼び出すことができます。それでも、私のリストには、ライブラリをコンパイルするとき、つまり明日、既知の型シグネチャを持つメソッドをリストできます。

非常にクリーンで、C#が私を狂わせることはありません。それでも、C#はサブタイプの関係を推測するのに十分な努力をしていません(申し訳ありませんが、エリック:「サブタイプの関係はどうあるべきか」)。ジェネリックはCのマクロではありません。それでも、C#は、それらをあたかもそうであるかのように扱うにはあまりにも近すぎます。

そして、それは私自身の(本当の)質問に答えます。

于 2010-12-22T23:09:58.393 に答える