从通用类型问题推断
我想这更像是公开的咆哮,但为什么我不能让 c# 来推断我的 Id 类型?
public EntityT Get<EntityT>(IdT id) where EntityT : EntityObject<IdT>
以及定义的 EntityObject,其 Guid 作为 Id,如下所示:
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);
进行编辑以提供进一步的说明。
I suppose this is more of a public rant, but why can't I get c# to infer my Id's type?
public EntityT Get<EntityT>(IdT id) where EntityT : EntityObject<IdT>
and a defined EntityObject with a Guid as an Id as follows:
public Foo : EntityObject<Guid>
Inheriting from the abstract EntityObject class defined as follows:
public abstract class EntityObject<IdT>
{
public IdT id { get; set; }
}
Usage of the get method would be as follows:
IRepository repository = new Repository();
var hydratedFoo = repository.Get<Foo>(someGuidId);
edited to provide further clarification.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
鉴于您只给出了两个声明,而不是如何使用它们,所以很难说。 IdT 是另一个类型参数吗? (如果它是
TId
,那就表明它是 - 但事实上,您使用EntityT
作为另一个类型参数,这与约定相反,表明可能IdT 也是如此...)
现在,假设在您的情况下
IdT
实际上是Guid
,编译器应该如何计算出您的意思是Foo ? 可能还有从
EntityObject
派生的其他类型。简而言之,您没有向我们提供足够的信息来确定任何事情,但听起来您基本上对编译器提出了不合理的要求。
编辑:好的,这是我对您所拥有的内容的猜测,使用正常的命名约定:
您想要执行的操作:
而目前您必须执行的操作:
是的,编译器使您的操作变得比必要的困难稍微 。 总共 6 个额外字符,是为了让语言更简单,类型推断的规则更容易理解。
基本上类型推断是一个全有或全无的事情 - 要么所有类型参数都被推断出来,或者没有一个被推断出来。 这使得事情变得简单,因为您不需要弄清楚哪些是被指定的,哪些是没有指定的。 这是问题的一部分,另一部分是您只能表达对方法的类型参数的约束 - 您不能这样做:
因为那是约束
TEntity
,而不是TId. 同样,这种事情使类型推断变得更简单。
现在您可以编写:
使用适当的
Get
方法和额外的接口。 我想我个人更喜欢只使用Get
。It's hard to say given that you've only given two declarations, not how you're using them. Is IdT another type parameter somewhere? (If it were
TId
, that would suggest it is - but the fact that you're usingEntityT
for another type parameter, contrary to conventions, suggests that maybeIdT
is as well...)Now, assuming
IdT
is actuallyGuid
in your case, how should the compiler work out that you meanFoo
? There could be other types deriving fromEntityObject<Guid>
.In short, you haven't given us enough information to tell anything for sure, but it sounds like you're basically making unreasonable demands on the compiler.
EDIT: Okay, here's my guess at what you have, using normal naming conventions:
You want to do:
Whereas currently you have to do:
Yes, the compiler is making it very slightly harder for you than necessary. A whole 6 extra characters, for the sake of keeping the language simpler and the rules of type inference easier to understand.
Basically type inference is an all or nothing affair - either all type parameters are inferred or none of them is. That keeps it simple as you don't need to work out which ones are being specified and which aren't. That's part of the problem, and the other part is that you can only express constraints on the type parameters of the method - you can't have:
because that's constraining
TEntity
, notTId
. Again, this sort of thing makes type inference simpler.Now you could potentially write:
with an appropriate
Get
method and an extra interface. I think I'd personally prefer to just useGet<Foo, Guid>
though.像这样的声明
要求 IdT 是具体类型。 如果您还想参数化 IdT,则需要使用
但这可能不是您想要的。
A declaration like
demands that IdT is an concrete type. If you want to parameterize IdT as well, you'd need to use
But that's probably not what you'd want.
这就是为什么我几乎放弃了具有通用实体的通用键类型。 我无法弄清楚如何让我的实体拥有通用键类型而不将这两种类型散布到各处。 现在我已经选择了整数键(无论如何我到处都有它),但感觉不对。
This is why I've all but given up on generic key types with generic entities. I could not figure out how to get my entities to have generic key types without sprinkling the two all over the place. Now I've settled on integer keys (which is what I have everywhere anyway) but it feels wrong.
如果您的方法签名如下所示:
编译器将有一些东西可以使用...
然后您可以使用以下内容调用 get :
编辑(我错了):
Product p = Get(id);Jon's他的帖子将这个答案钉在了顶部,所以我会闭嘴并爬回我的洞里。
If your method signature looked like this:
The compiler would have something to work with...
You then call get with something like:
EDIT (I was wrong):
Product p = Get(id);Jon's nailed this answer with his post up top so I'll shut up and crawl back in my hole.