2009-08-11 8 views
6

これはもっと一般的な暴言だと思うけど、なぜ私のIDのタイプを推測するC#を得ることができないのですか?一般的なタイプからの推測質問

public EntityT Get<EntityT>(IdT id) where EntityT : EntityObject<IdT> 

と、次のようにIDとしてGUIDを持つ定義さEntityObject:として定義された抽象EntityObjectクラスから継承

public Foo : EntityObject<Guid> 

は次のとおりです。getメソッドの

public abstract class EntityObject<IdT> 
{ 
    public IdT id { get; set; } 
} 

使い方を考え

IRepository repository = new Repository(); 
var hydratedFoo = repository.Get<Foo>(someGuidId); 

がさらに明確になるように編集されています。

答えて

3

2つの宣言を与えただけで、使用方法はわかりません。 IdTは別の型パラメータですか? IdTがあると仮定すると、今

を - (ただし、規則に反して別の型パラメータのEntityTを、使用しているという事実は、...多分IdTも同様であることを示唆している、それはTIdだったら、それはそれは示唆しています)あなたのケースでは実際にGuid、コンパイラはどのようにしてFooを意味するのでしょうか? EntityObject<Guid>に由来する他のタイプもあります。

要するに、何かを伝えるための十分な情報は与えていませんが、基本的にはコンパイラに不合理な要求があるようです。

EDIT:さて、ここでは通常の命名規則を使用して、あなたが持っているもので、私の推測です:

public interface IRepository 
{ 
    TEntity Get<TEntity, TId>(TId id) where TEntity : EntityObject<TId> 
} 

public abstract class EntityObject<TId> 
{ 
    public IdT id { get; set; } 
} 

public class Foo : EntityObject<Guid> {} 

あなたがやりたい:

IRepository repository = GetRepositoryFromSomewhere(); 
Foo foo = repository.Get<Foo>(someGuid); 

現在、あなたがしなければならないのに対し:

Foo foo = repository.Get<Foo, Guid>(someGuid); 

はい、コンパイラはを少し作成しています必要以上にあなたのために難しい。言語をよりシンプルにし、型推論の規則を理解しやすくするために、6文字の余分な文字

基本的に型推論は、すべてまたは何も関係しません。すべて型パラメータが推論されるか、いずれも推測されません。それは、あなたが特定されているものとそうでないものを見つけ出す必要がないので、それを簡単に保ちます。これは、問題の一部だし、他の部分は、あなたが唯一の方法の型パラメータの制約を表現することができるということです - あなたは持っていないことができます。

class Repository<TEntity> 
{ 
    TEntity Get<TId>(TId id) where TEntity : EntityObject<TId> 
} 

をそれがTIdTEntityはない制約だからです。ここでも、このようなことは型推論を簡単にします。

今、あなた潜在的に書くことができます:

Foo foo = repository.Get(someGuid).For<Foo>(); 

適切なGet方法と、余分なインターフェースで。私は個人的にちょうどGet<Foo, Guid>を使用することを好むだろうと思う。

+1

ジョン、詳細を追加しないことをお詫び申し上げます。これは本当に正当な疑問ではなく、カフの暴言から離れていました。しかし、imhoコンパイラはコンパイル時にfooオブジェクトからIdTを決定できるはずです。 ほとんどの場合、ジェネリックのための私の前提ですが、コンパイラがこれをどのように読むことができるかの解釈が間違っていますが、コンパイル時までジェネリック型が決まっていないと仮定しました。テンプレートオブジェクト。それが、参照されるオブジェクトのタイプを決定することがさらに一歩前進しないと仮定します。 – Raspar

+0

Generics!= Templates。あなたはおそらく、そのようなことを「推論する」C++コンパイラを手に入れることができますが、ジェネリックがランタイムである限り、より明示的な一般的な定義なしには起こりません。 – user7116

+0

IdTは 'Get'の型パラメータではありません。これは型パラメータが' EntityT'だけです。あなたはIRepositoryの宣言をしていないか、あなたのために働いていないものを与えていません。あなたがしようとしていることを示して、あなたが望むものの代わりに何が起こったのかを伝える*完全な例を挙げてください。 –

0

あなたのメソッドのシグネチャは、このように見えた場合:

public TEntity Get<TEntity, TId>(TId id) where TEntity : EntityObject<TId> 

をコンパイラがで動作するように何かを持っているでしょう...

そのあとのようなものを取得呼び出します。

EDIT(私がいました間違っている): プロダクトp = Get(id);

Product p = Get<Product, Guid>(id); 

Jonの彼のポストアップトップと、この答えはので、私は黙っだろうと戻って私の穴にクロール釘付け。

+0

これは確かに機能しますが、FooのキーがGuidであることは誰にとっても痛感することです。 – n8wrl

+0

@ n8wrl私はあなたのコメントを理解していません。 – grenade

+0

本当のロブ、私はあなたの答えRepository.Get (someGuid)は、各エンティティのIDの種類を知っている開発者が必要です。また、Repository.Get (someGuid)が持つ構文上の甘さも欠けています。 – Raspar

0

IDTが具象型である

public EntityT Get<EntityT>(IdT id) where EntityT : EntityObject<IdT> 

要求等宣言。 Idtをパラメータ化する場合は、

public EntityT Get<EntityT, IdT>(IdT id) where EntityT : EntityObject<IdT> 

を使用する必要がありますが、それはおそらくあなたが望むものではありません。

0

これは、汎用エンティティを持つ汎用キータイプをすべて諦めてしまった理由です。私はエンティティにジェネリックキータイプを持たせる方法を理解することができませんでした。今私は整数キー(これは私がどこにいても)を解決しましたが、それは間違っています。

+0

まさに!当面はGuidsを使用していましたが、今では複合IDのアイデアを扱うレガシーデータベースを組み込む必要があります。うん。 – Raspar

+0

タイプ推論を検出したい。ジェネリックメソッドを呼び出すときは、明示的にする必要はありません。 – grenade

+0

@Rob:まあ、時々あなたはしないし、時にはあなたがします。それは正確な状況に依存します。 –

関連する問題