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