C# の typeof(IEnumerable<>) に相当する F#
-
21-09-2019 - |
質問
特定の型が実装されているかどうかを確認する必要があるコードがあります。 IEnumerable<T>
(Tは気にしない)
私はもう試した (t:System.Type
疑問に思われる場合に備えて)
let interfaces = t.GetInterfaces()
let enumerbale =
interfaces.Any(fun t ->
t.GetGenericTypeDefinition() = typeof<IEnumerable<>>
)
ただし、これはコンパイルされません (コンパイルは <> を好みません)。それから試してみました
let interfaces = t.GetInterfaces()
let enumerbale =
interfaces.Any(fun t ->
t.GetGenericTypeDefinition() = typeof<IEnumerable<'a>>
)
しかし、「a は obj に対する制約です」という警告が表示されます。どうか知りたくない IEnumerable<obj>
実装されていますが、 IEnumerabl<>
.
解決策を知っている人はいるので、上記のコードについてもお気軽にコメントしてください。
解決
これは動作するはずます:
typedefof<System.IEnumerable<_>>
編集
としてトーマス・ノートには、ワイルドカードここ_
について何も特別ながあります。型obj
は、この文脈の中で最も一般的な適用可能なタイプであるので、これはtypedefof<System.IEnumerable<obj>>
を使用するのと同じであることはF#の推論。いくつかのケースでの方法は、この作品は、しかし、障害のビットをすることができます。あなたは、インタフェースtype I<'a when 'a :> I<'a>> = interface end
を定義した場合たとえば、その後、typedefof<I<_>>
は、一般的な制約を満たしていないので、あなたは、I<obj>
を使用することはできませんし、F#は、別のより適切な型を推測することはできません。これは、例えばtype I<'a when 'a : struct and 'a :> System.ICloneable> = interface end
(さえ再帰的制約なしに起こることができる。これは、類似のケースでは完全に正常に動作しC#のアプローチとは対照的である。
あなたのコード自体に関しては、私はあなたがそのようなインタフェースはGetGenericTypeDefinition
を呼び出す前に、汎用であることを確実にすることなど、あまりにも他のいくつかの変更を、作りたいと思います。ここで私はテスト関数を記述します。方法は次のとおりです。
(fun t -> t.IsGenericType && (t.GetGenericTypeDefinition() = typedefof<_ seq>))
他のヒント
私の知る限りでは、F#は、C#のtypeof(IEnumerable<>)
に任意の同等を持っていません。これは、C#で明示的にサポートする特殊な構文であるためです。 F#では、typeof
は通常の関数であり、type引数には、完全に指定された型である必要があります。あなたは、このようにプログラム的にジェネリック型定義を取得することができます:
let t = typeof<IEnumerable<obj>>
let genericT = t.GetGenericTypeDefinition()
IEnumerable<'a>
とあなたの解決策の問題は(ジェネリック型定義として有効なタイプではない)F#コンパイラは、まだ使用にいくつかの具体的なタイプを見つける必要があるということです。型パラメータがどのような方法で制限されていないことを型推論演繹した場合、それはobj
あるデフォルトのタイプを使用します。
編集私は非常に有用である、typedefof<IEnumerable<_>>
知りませんでした!とにかく、アンダースコアがここで特別な意味を持っていないことに注意してください - 実型引数は、まだIEnumerable<obj>
ですが、typedefof
機能は、シーンの背後にあるGetGenericTypeDefinition
を呼び出します。
この質問は、その答えが次のリンクに掲載されている多くの質問のうちの 1 つであることを指摘しないのは不謹慎です。