类型参数'T'的名称与外部类型'...'的类型参数相同。

24
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<U>(int x) { Foo(x); },但是这样做无法保证U和T相同。由于Foobar类的实现方式非常重要,所以它们必须相同。
我还尝试过这样做:void IFoobar.Foo<U>(int x) where U : T { Foo(x); },但是这并不能保证U和T相等,也不能重新定义约束条件,因为它已经在接口中定义了。

2
你试图做什么?如果在类中已经指定了T,为什么要重新定义它?如果您需要定义它,则应该将其分开,否则T已由类指定。如果您想解决这个问题,如果可以的话,请将T放在接口上。当我发现自己重复类型规范时,这就是我所做的。 - Timothy Gonzalez
3个回答

15
最大的问题是你的接口定义不明确,与代码意图不符。如果你的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();
}

请见如IEnumerableICollectionIList等接口,这些接口是此类设计的示例。
但是,请仔细考虑。这种最后的设计妥协(同时具有通用和对象版本)总会有所不足。
您需要放弃以下之一:
- 直接传达设计契约的良好接口设计(如果传入错误类型时抛出异常或执行无操作) - 类型安全性及其减少错误的效果(如果正确地操作任意对象)

11

您可以选择以下两种方式之一:

  1. Ignore the warning and make both types T.
  2. Do a run-time check and throw an exception:

    if (typeof(T) != typeof(U)) throw Exception("Not the same type");
    

正如其他人所说,也许你需要重新考虑设计界面的方式。



5

只是尝试

void IFoobar.Foo<U>(int x) { Foo(x); }

当然,这仍然不能保证UT相同。你无法在编译时强制执行它,因为当你实现一个接口时,你必须遵循它的规则 -- IFoobar没有对Foo<T>施加这样的限制,如果你这样做了,你将不再实现该接口(根据定义,因为你更加严格,但你声称你没有)。
你可以尝试在运行时检查它,虽然这有点“作弊”(因为你也不真正符合接口)。

虽然这保持了类型的限制,但并不能保证 TU 是相同的。 - Ken Wayne VanderLinde
这并不保证U等于T,而且我不能重新定义U的约束条件,因为它们是在接口中定义的。 - michael
这段代码无法编译。重写方法和显式接口实现方法的约束从基本方法继承,因此不能直接指定。删除where子句以解决此问题。 - Merlyn Morgan-Graham
@Merlyn:糟糕,我的错,已经修复了。 - user541686
1
+1;你关于接口设计和运行时检查的最后几点与接受“对象”时的问题是一样的。基本上,你抛弃了类型安全性。在这种情况下,甚至更糟糕,因为它在表面上看起来是类型安全的。 - Merlyn Morgan-Graham

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接