【问题标题】:How many interfaces are allowed to be implemented?允许实现多少个接口?
【发布时间】:2011-05-16 04:41:26
【问题描述】:

在 C# 中:

一个类可以同时实现多少个接口

public class MyClass: IInteferface_1, IInterface_2, ... , IInterface_N
{
}

N 有限制吗?

别担心,我不想实现或维护这样的对象。我只是想知道是否有限制。

【问题讨论】:

  • 我认为这是一个完全有效的问题,因为答案不仅有助于理解语言的局限性,而且还可以帮助程序员决定如何构建代码。

标签: c# .net interface interface-implementation


【解决方案1】:

C#语言对接口的数量没有限制。但是有两个实际限制。

首先,正如 chibacity 所指出的,编译器在处理大量接口或极深的接口层次结构时最终会耗尽堆或堆栈空间。

即使我们解决了这些问题,仍然会有第二个问题。接口实现在 InterfaceImpl 表中的元数据中编码。元数据表的成员通常不超过 2^24 个,因此程序集中所有类型实现的接口的总数必须少于大约 1600 万。

显然,您在实践中永远不会遇到这些限制。不用担心。

【讨论】:

  • @Eric:你知道为什么限制是 2^24 吗?只是好奇为什么这个数字。是否与元数据表本身使用的限制为 2^24 的类型有关?
  • @Joan:Eric 是 MS 的 C# 语言团队的一员,所以即使元数据限制没有记录(例如在 ECMA 标准中),他也有内部信息。
  • @Joan:好问题。元数据令牌是一个四字节整数,其中最高字节标识令牌的种类。例如,“TypeDef”令牌的最高字节为 0x02。剩下 24 位用于令牌的其余部分。
  • @Eric:感谢 Eric 的解释。现在我知道为什么了:O
  • 有一个较早的限制,一个类型不能超过 65536 个成员。当 C++ 程序员在 all 他们的代码上翻转 /clr 选项并将他们的非托管函数和全局变量塞进一个超类时,他们经常会遇到它。我以为是元数据令牌,但检查 335 后似乎不是。
【解决方案2】:

您可以实现的接口数量受限于编译器可以处理的内容。太多接口会导致 C# 编译器中的 stackoverflow 异常(错误 CS1647)。这会让我相信没有固定的限制,但在某些情况下编译器会简单地炸弹,即数量将取决于编译器处理类时可用的堆栈空间。

该限制也可能取决于编译器版本。下面的代码可以用来生成一个测试用例来探测极限。

    int iterations = (int)Math.Pow(2, 8) + 1;

    Func<int, string> getInterfaceName = i => "I" + i;

    StringBuilder sb = new StringBuilder();

    sb.AppendLine("using NUnit.Framework;");
    sb.AppendLine("[TestFixture]");

    sb.AppendLine("public class Test");
    sb.AppendLine("{");

    sb.AppendLine("[Test]");
    sb.AppendLine("public void bling()");
    sb.AppendLine("{");
    sb.AppendLine("Class1 class1 = new Class1();");

    for (int i = 0; i < iterations; i++)
    {
        sb.AppendLine(getInterfaceName(i) + " int" + i + " = class1;");
        sb.AppendLine("int" + i + ".Bling();");
    }

    sb.AppendLine("}");

    for (int i = 0; i < iterations; i++)
    {
        sb.AppendLine("public interface " + getInterfaceName(i) + " { void Bling(); }");
    }

    sb.Append("public class Class1 : " + getInterfaceName(0));

    for (int i = 1; i < iterations; i++)
    {
        sb.Append(", " + getInterfaceName(i));
    }

    sb.Append("{ public void Bling(){} }");

    sb.AppendLine("}");

    File.WriteAllText(@"C:\tmp.cs", sb.ToString());

【讨论】:

  • 天哪。用 C# 编写脚本。
【解决方案3】:

如果您问这个问题是为了实际实现大量接口,我会说您有一个严重的设计问题。

据我所知,除了你的电脑内存没有限制。

【讨论】:

  • +1 因为你的回答让我笑了。因为这是真的。
  • 据我所知,没有限制但不确定。
  • Liviu,我快速搜索了一下,但很难找到明确的答案,因为它不是一个常见问题。所以不,我不能确定没有绝对限制。也许你可以做一些测试并找出:-)
【解决方案4】:

考虑一下MyClass: IInteferface_1, IInterface_2, ... , IInterface_N 对编译器/运行时的实际意义。没有设计时间限制,因为编译器只是确保您的类对于它应该实现的每个接口都有适当的(方法)签名。至于运行时间限制,我认为内存不会产生太大影响,因为通过它实现的接口(在设计时验证)对您的类的任何引用只会确保您的类具有该接口的适当方法签名。如果对象没有实现接口,则该对象将缺少方法签名。

【讨论】:

    【解决方案5】:

    我刚刚检查了 Microsoft C♯ 语言规范版本 4.0 的当前版本,并且没有提及 §1.6.4、§1.9、§10.1.4、§10.1.4.2 和 §13 中的限制。 §B.2.7 中的语法也没有句法限制。

    我显然没有阅读完整的 500 页,但我不知道该文档中的其他地方可能会提到限制。

    注意:这仅适用于 Microsoft C♯,并且仅适用于 4.0 版。我没有检查 Microsoft C♯ 的早期版本,也没有检查 ECMA/ISO C♯。此外,它仅适用于 C♯,CLI 中可能存在限制。

    最后但同样重要的是,Microsoft Visual C♯ 和 Novell Mono C♯ 中可能存在特定于实现的限制,以及 Microsoft 和 Mono 的 CLI 实现(即 CLR 和 Mono VM)中的特定于实现的限制)。

    但是,问题是关于 C♯,而不是关于 C♯ 的任何特定实现,也不是关于 CLI,所以我很有信心声称一个类可以实现的接口数量是无限的。

    【讨论】:

      【解决方案6】:

      有限制

      您被限制为 255,因为单个字节被 JIT 用作相关接口的类型表的索引器。

      【讨论】:

      • 终于有一个科学的答案(+1),有人可以确认吗?
      • 你会参考一些文章吗?
      • -1 我做了一个小实验,能够编译出一个实现 10 * 1000 个接口的类,所以 256 的限制是不正确的。
      • 它不是编译器限制,而是 JIT 限制 - 尝试在具有通过超过 255 个接口多态利用类的代码的应用中运行它
      • @Dean 另一个快速测试。成功构造了一个实现257个接口的类,并通过每个接口访问该类。没问题。
      猜你喜欢
      • 2012-11-19
      • 1970-01-01
      • 1970-01-01
      • 2019-03-08
      • 1970-01-01
      • 2012-10-16
      • 1970-01-01
      • 1970-01-01
      • 2015-05-13
      相关资源
      最近更新 更多