类型参数“T”与外部类型的类型参数具有相同的名称 '...'
public abstract class EntityBase { ... }
public interface IFoobar
{
void Foo<T>(int x)
where T : EntityBase, new();
}
public interface IFoobar<T>
where T : EntityBase, new()
{
void Foo(int x);
}
public class Foobar<T> : IFoobar, IFoobar<T>
where T : EntityBase, new()
{
public void Foo(int x) { ... }
void IFoobar.Foo<T>(int x) { Foo(x); }
}
我收到编译器警告: 类型参数 'T' 与外部类型 '...' 的类型参数同名
我尝试这样做: void IFoobar.Foo(int x) { Foo(x); }
,但是我不能保证 U 和 T 是相同的。 Foobar 类的实现方式非常重要,它们必须相同。
我也尝试这样做: void IFoobar.Foo(int x) where U : T { Foo(x); }
,但这并不能保证 U 和 T 相等,并且不允许我重新定义约束,因为它是在接口上定义的。
public abstract class EntityBase { ... }
public interface IFoobar
{
void Foo<T>(int x)
where T : EntityBase, new();
}
public interface IFoobar<T>
where T : EntityBase, new()
{
void Foo(int x);
}
public class Foobar<T> : IFoobar, IFoobar<T>
where T : EntityBase, new()
{
public void Foo(int x) { ... }
void IFoobar.Foo<T>(int x) { Foo(x); }
}
I get a compiler warning: Type parameter 'T' has the same name as the type parameter from outer type '...'
I tried doing: void IFoobar.Foo<U>(int x) { Foo(x); }
, however then I can't guarantee that U and T are the same. The way that the Foobar class is implemented, it is very important that they be the same.
I also tried doing: void IFoobar.Foo<U>(int x) where U : T { Foo(x); }
, however that does not guarantee that U and T are equal and it does not allow me to redefine the constraint since it was defined on the interface.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
最大的问题是您的接口定义不明确,并且与代码的意图不匹配。
如果您的
T
在界面上不公开可见,则外部代码甚至不必知道存在T
。您需要创建接收或返回T
的方法,或者拥有一些T
类型的属性,或者您应该完全摆脱T
,并使您的接口成为非通用的。一旦你支持了这一点,为什么你不需要两个不同的接口就应该变得更加明显,并且你不应该再需要协调它们。
如果事实证明您确实需要一个采用
T
的版本和一个非T版本,那么更惯用的方法是传递对象
而不是T
:有关示例,请参阅
IEnumerable
、ICollection
、IList
等接口。但请仔细考虑。最后的设计妥协(同时具有通用版本和对象版本)总是留下一些不足之处。
您将牺牲其中之一:
The biggest problem is that your interfaces are not well defined, and do not match the intent of your code.
If your
T
is not publicly visible on the interface, then external code doesn't even have to know there is aT
. You need to either make methods that receive or returnT
, or have some property of typeT
, or you should simply get rid ofT
entirely, and make your interfaces non-generic.Once you shore this up, it should become more obvious why you don't need two different interfaces here, and you should no longer have to reconcile them.
If it turns out that you do need a version that takes
T
, and a non-T version, then the more idiomatic way to do this is pass aroundobject
instead ofT
:See interfaces like
IEnumerable
,ICollection
,IList
, etc for examples of this.But consider carefully. This last design compromise (having both a generic and object version) always leaves something to be desired.
You'll sacrifice one of these:
您可以执行以下两种操作之一:
执行运行时检查并引发异常:
正如其他人所说,也许您需要重新考虑设计界面的方式。
You can do one of two things:
Do a run-time check and throw an exception:
As others have stated, perhaps you need to rethink the way you are designing your interfaces.
试试吧
当然,这仍然不能保证施加这样的限制,如果这样做,您将不再实现该接口(根据定义,因为您更加严格,但您声称你不)。
U
与T
相同。您无法在编译时强制执行这一点,因为当您实现接口时,您必须遵循其规则——而IFoobar
不会对 Foo您可以尝试在运行时检查它,尽管这有点“作弊”(因为您也没有真正遵守接口)。
Just try
Of course, that still doesn't guarantee that
U
is the same asT
. You can't enforce that at compile-time, because when you're implementing an interface, you must follow its rules -- andIFoobar
doesn't put such a restriction onFoo<T>
, and if you do, you would no longer be implementing the interface (by definition, since you are being stricter, and yet you're claiming that you're not).You can try checking it at run time instead, although that's somewhat "cheating" (since you're not really conforming to the interface then either).