[解決済み] なぜC#は私のジェネリック型を推論しないのですか?
質問
私はジェネリックメソッドでたくさんのFuncy楽しい(楽しみを意図して)持っています。ほとんどの場合、C# の型推論は十分に賢く、私のジェネリック メソッドで使用しなければならないジェネリック引数を見つけることができますが、今私は、C# コンパイラーが正しい型を見つけることに成功したと信じている一方で、成功しないデザインを手に入れました。
この場合、コンパイラーは少し頭が悪いのか、それとも私のジェネリック引数を推論できない非常に明確な理由があるのか、誰か教えていただけませんか。
これがそのコードです。
クラスとインターフェースの定義です。
interface IQuery<TResult> { }
interface IQueryProcessor
{
TResult Process<TQuery, TResult>(TQuery query)
where TQuery : IQuery<TResult>;
}
class SomeQuery : IQuery<string>
{
}
コンパイルできないコードもあります。
class Test
{
void Test(IQueryProcessor p)
{
var query = new SomeQuery();
// Does not compile :-(
p.Process(query);
// Must explicitly write all arguments
p.Process<SomeQuery, string>(query);
}
}
これはなぜでしょうか?何が足りないのでしょうか?
これがコンパイラのエラーメッセージです(あまり想像の域を出ませんね)。
メソッドIQueryProcessor.Process<TQuery.TResult>の型引数は、使用方法から推測できません。 TResult>(TQuery) の型引数は、使用方法から推測することができません。明示的に を明示的に指定してみてください。
C#が推論できるはずだと思うのは、次のような理由です。
-
を実装したオブジェクトを提供する。
IQuery<TResult>
. -
それのみ
IQuery<TResult>
のバージョンは、その型が実装しているIQuery<string>
でなければならず、したがって TResult はstring
. - この情報により、コンパイラはTResultとTQueryを持つことになります。
どのように解決するのですか?
これは元々 質問 に投稿されたもので、OPに代わってここに移動されました。
私にとっての最良の解決策は
IQueryProcessor
インターフェースを変更し、実装で動的型付けを使用することでした。
public interface IQueryProcessor
{
TResult Process<TResult>(IQuery<TResult> query);
}
// Implementation
sealed class QueryProcessor : IQueryProcessor {
private readonly Container container;
public QueryProcessor(Container container) {
this.container = container;
}
public TResult Process<TResult>(IQuery<TResult> query) {
var handlerType =
typeof(IQueryHandler<,>).MakeGenericType(query.GetType(), typeof(TResult));
dynamic handler = container.GetInstance(handlerType);
return handler.Handle((dynamic)query);
}
}
は
IQueryProcessor
インタフェースは、現在
IQuery<TResult>
パラメータを受け取るようになりました。こうすることで
TResult
を返すことができ、これで消費者の立場から見た問題は解決します。具体的なクエリ型が必要なので(私の場合)、実際の実装を得るために実装でリフレクションを使う必要があります。しかし、ここでダイナミックタイピングが登場し、私たちのためにリフレクションを行ってくれる。これについては、以下の記事を参照してください。
記事
.
関連
-
[解決済み】C# ASP.NET使用時に「WebClientのリクエスト中に例外が発生しました。
-
[解決済み] [Solved] アセンブリ System.Web.Extensions dll はどこにありますか?
-
[解決済み】なぜこのコードはInvalidOperationExceptionを投げるのですか?
-
[解決済み】Unity 「関連するスクリプトを読み込むことができません」「Win32Exception: システムは指定されたファイルを見つけることができません"
-
[解決済み】URLから画像をダウンロードする方法
-
[解決済み] なぜList<T>を継承しないのですか?
-
[解決済み] C#でHashtableよりDictionaryが好まれる理由とは?
-
[解決済み] リフレクションを使ってジェネリックメソッドを呼び出すにはどうしたらいいですか?
-
[解決済み] なぜC#は汎用属性型を禁止しているのですか?
-
[解決済み】TをEnumに拘束するGenericメソッドの作成
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] エンティティタイプ ApplicationUser は、現在のコンテキストのモデルの一部ではありません。
-
[解決済み】ソケットのアドレス(プロトコル/ネットワークアドレス/ポート)は、通常1つしか使用できない?
-
[解決済み】バックスラッシュを含むパス文字列のエスケープシーケンスが認識されない件
-
[解決済み] 'IEnumerable<SelectListItem>' 型の ViewData アイテムで、キーが国であるものは存在しない。
-
[解決済み] EntityTypeにキーが定義されていないエラー
-
[解決済み】OnCollisionEnter2Dが実行されない?
-
[解決済み】Linq 構文 - 複数列の選択
-
[解決済み] 2つのリストを結合する
-
[解決済み】URLから画像をダウンロードする方法
-
[解決済み】プロセスが実行されているかどうかを知るには?