类型参数“T”与外部类型的类型参数具有相同的名称 '...'

发布于 2024-11-24 16:46:39 字数 752 浏览 2 评论 0原文

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

私藏温柔 2024-12-01 16:46:39

最大的问题是您的接口定义不明确,并且与代码的意图不匹配。

如果您的 T 在界面上不公开可见,则外部代码甚至不必知道存在 T。您需要创建接收或返回 T 的方法,或者拥有一些 T 类型的属性,或者您应该完全摆脱 T ,并使您的接口成为非通用的。

一旦你支持了这一点,为什么你不需要两个不同的接口就应该变得更加明显,并且你不应该再需要协调它们。

如果事实证明您确实需要一个采用T的版本和一个非T版本,那么更惯用的方法是传递对象 而不是 T

public interface IFoo
{
    void DoSomething(object o);
    object DoSomethingElse();
}

public interface IFoo<T>
{
    void DoSomething(T item);
    T DoSomethingElse();
}

有关示例,请参阅 IEnumerableICollectionIList 等接口。

但请仔细考虑。最后的设计妥协(同时具有通用版本和对象版本)总是留下一些不足之处。

您将牺牲其中之一:

  • 直接传达设计契约的良好接口设计(如果您在传入错误类型时引发异常或执行无操作)
  • 类型安全性,以及随之而来的错误的减少(如果您可以正确操作任何旧对象)

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 a T. You need to either make methods that receive or return T, or have some property of type T, or you should simply get rid of T 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 around object instead of T:

public interface IFoo
{
    void DoSomething(object o);
    object DoSomethingElse();
}

public interface IFoo<T>
{
    void DoSomething(T item);
    T DoSomethingElse();
}

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:

  • Good interface design that directly communicates a design contract (If you throw exceptions or do a no-op when the wrong type is passed in)
  • Type safety, and the reduction in bugs that goes with it (if you correctly operate on any-old-object)
傾城如夢未必闌珊 2024-12-01 16:46:39

您可以执行以下两种操作之一:

  1. 忽略警告并将两种类型设置为 T。
  2. 执行运行时检查并引发异常:

    if (typeof(T) != typeof(U)) throw Exception("类型不同");
    

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

You can do one of two things:

  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");
    

As others have stated, perhaps you need to rethink the way you are designing your interfaces.

柠北森屋 2024-12-01 16:46:39

试试吧

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

当然,这仍然不能保证 UT 相同。您无法在编译时强制执行这一点,因为当您实现接口时,您必须遵循其规则——而IFoobar不会对 Foo施加这样的限制,如果这样做,您将不再实现该接口(根据定义,因为您更加严格,但您声称你不)。

您可以尝试在运行时检查它,尽管这有点“作弊”(因为您也没有真正遵守接口)。

Just try

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

Of course, that still doesn't guarantee that U is the same as T. You can't enforce that at compile-time, because when you're implementing an interface, you must follow its rules -- and IFoobar doesn't put such a restriction on Foo<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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文