mic*_*ael 17 c# generics interface constraints explicit-interface
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); }
}
Run Code Online (Sandbox Code Playgroud)
我收到编译器警告: Type parameter 'T' has the same name as the type parameter from outer type '...'
我尝试过:void IFoobar.Foo<U>(int x) { Foo(x); }但是我不能保证U和T是一样的.Foobar类的实现方式,它们是相同的非常重要.
我也尝试过:void IFoobar.Foo<U>(int x) where U : T { Foo(x); }但是这并不保证U和T是相等的,并且它不允许我重新定义约束,因为它是在接口上定义的.
Mer*_*ham 12
最大的问题是您的接口定义不明确,并且与您的代码意图不符.
如果您T的界面上没有公开显示,那么外部代码甚至不必知道有T.您需要创建接收或返回的方法T,或者具有某种类型的属性T,或者您应该完全摆脱T,并使您的接口非泛型.
一旦你坚持下去,为什么你不需要两个不同的接口就应该变得更加明显,你不应该再调和它们了.
如果事实证明你确实需要一个版本T和非T版本,那么更惯用的方法是传递object而不是T:
public interface IFoo
{
void DoSomething(object o);
object DoSomethingElse();
}
public interface IFoo<T>
{
void DoSomething(T item);
T DoSomethingElse();
}
Run Code Online (Sandbox Code Playgroud)
看到这样的接口IEnumerable,ICollection,IList等了这方面的例子.
但要仔细考虑.最后的设计折衷(同时具有通用版本和对象版本)总是有所不足.
你将牺牲其中一个:
你可以做以下两件事之一:
执行运行时检查并抛出异常:
if (typeof(T) != typeof(U)) throw Exception("Not the same type");
Run Code Online (Sandbox Code Playgroud)正如其他人所说,也许您需要重新思考设计界面的方式.
你试一试
void IFoobar.Foo<U>(int x) { Foo(x); }
Run Code Online (Sandbox Code Playgroud)
当然,这仍然不能保证与U相同T。您不能在编译时强制执行这一点,因为当您实现接口时,您必须遵循其规则——并且IFoobar不会对 施加这样的限制Foo<T>,如果这样做,您将不再实现该接口(根据定义,因为您更加严格,但您却声称自己并不严格)。
您可以尝试在运行时检查它,尽管这有点“作弊”(因为您也没有真正遵守接口)。