很难说你只给出了两个声明,而不是你如何使用它们。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>
。