我认为这更像是公开咆哮,但为什么我不能用c#来推断我的Id类型?
public EntityT Get<EntityT>(IdT id) where EntityT : EntityObject<IdT>
和定义的具有Guid作为Id的EntityObject如下:
public Foo : EntityObject<Guid>
继承自如下定义的抽象EntityObject类:
public abstract class EntityObject<IdT>
{
public IdT id { get; set; }
}
get方法的用法如下:
IRepository repository = new Repository();
var hydratedFoo = repository.Get<Foo>(someGuidId);
编辑以进一步澄清。
答案 0 :(得分:3)
很难说你只给出了两个声明,而不是你如何使用它们。 IdT是某个地方的另一个类型参数吗? (如果它是TId
,那表明它是 - 但事实上你使用EntityT
作为另一个类型参数,与惯例相反,表明也许IdT
也是如此。 ..)
现在,假设IdT
实际上是Guid
,那么编译器应如何解决Foo
?可能还有其他类型派生自EntityObject<Guid>
。
简而言之,你没有给我们足够的信息来肯定地说出任何信息,但听起来你基本上对编译器提出了不合理的要求。
编辑:好的,这是我对你所拥有的东西的猜测,使用正常的命名约定:
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>
}
因为这会限制TEntity
,而不是TId
。同样,这种事情使类型推断更简单。
现在你可以写下:
Foo foo = repository.Get(someGuid).For<Foo>();
使用适当的Get
方法和额外的接口。我想我个人更愿意只使用Get<Foo, Guid>
。
答案 1 :(得分:0)
如果您的方法签名如下所示:
public TEntity Get<TEntity, TId>(TId id) where TEntity : EntityObject<TId>
编译器可以使用...
然后用以下内容调用get:
编辑(我错了):产品p =获取(id);
Product p = Get<Product, Guid>(id);
Jon在他的帖子顶部钉了这个答案,所以我会闭嘴并爬回我的洞里。
答案 2 :(得分:0)
像
这样的宣言public EntityT Get<EntityT>(IdT id) where EntityT : EntityObject<IdT>
要求IdT是具体类型。如果您想同时参数化IdT,则需要使用
public EntityT Get<EntityT, IdT>(IdT id) where EntityT : EntityObject<IdT>
但那可能不是你想要的。
答案 3 :(得分:0)
这就是为什么我几乎放弃了通用实体的通用密钥类型。我无法弄清楚如何让我的实体拥有通用密钥类型而不会将两者全部洒在地方。现在我已经确定了整数键(这是我到处都有的)但是感觉不对。