2010-11-26 103 views
20

在C#中:允許實現多少個接口?

一個類可以實現多少接口在同一時間

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

N是否有限制?

別擔心我不想實現或維護這樣的對象。我只是想知道是否有限制。

+2

Okie,你可以隨心所欲地減退,但我會再次downvote爲這樣的不真實的問題問。 – TalentTuner 2010-11-26 14:46:17

+5

我認爲這是一個完全有效的問題,因爲答案不僅有助於理解語言的侷限性,還可以幫助程序員決定如何構造代碼。 – 2012-11-12 18:20:58

回答

35

的C#語言規定上的接口數量沒有限制。雖然有兩個實際限制。

首先,正如chibacity所指出的那樣,編譯器在處理大量接口或接口的極深層次結構時最終會耗盡堆或堆棧空間。

即使我們解決了這些問題,仍然會有第二個問題。接口實現在InterfaceImpl表中的元數據中編碼。元數據表通常不會超過2^24個成員,因此組件中所有類型實現的接口數量必須少於約1600萬。

顯然你在實踐中永遠不會遇到這些限制。不要擔心。

8

如果你問,以實際執行的接口很多這個問題,我說你有一個嚴重的設計問題。

據我所知,沒有比計算機的內存等限制。

+2

+1,因爲你的回答讓我感動。因爲這是真的。 – David 2010-11-26 13:19:37

+0

也據我所知,沒有限制,但不知道。 – 2010-11-26 13:20:33

+0

嗯利維烏,我做了一個快速搜索,但很難找到明確的答案,因爲它不是一個常見的問題。所以不,我不能確定這絕對沒有限制。也許你可以做一些測試,並找出`:-)` – Nobody 2010-11-26 13:23:51

-5

有一個極限

您被限制到255作爲一個單一的字節被用作由JIT到該類型表的相關接口的索引器。

1

考慮一下它實際上意味着編譯/運行時間再說MyClass: IInteferface_1, IInterface_2, ... , IInterface_N。沒有設計時間限制,因爲編譯器只是確保您的類對其應該實現的每個接口都有適當的(方法)簽名。至於運行時間限制,我認爲內存不會有太大的影響,因爲通過它實現的接口(如在設計時驗證的)對類的任何引用都將確保您的類具有該接口的適當方法簽名。如果對象沒有實現接口,則該對象將缺少方法簽名。

1

我只是檢查了微軟C♯語言規範4.0版的最新版本,並沒有一個限制提§1.6.4,§1.9,§10.1.4,§10.1.4.2和§13。 §B.2.7中的語法也沒有語法限制。

我顯然沒讀完整個500頁,但我不知道還有什麼地方該文件中的限制可能會被提及。

注:這僅適用於MicrosoftC♯,只有到4.0版本。我沒有檢查早期版本的MicrosoftC♯,也沒有檢查ECMA/ISOC♯。此外,它僅適用於C♯,CLI中可能有限制。

最後但並非最不重要的一點是,Microsoft VisualC®和Novell MonoC®中可能存在實現特定的限制,以及Microsoft和Mono的CLI實現中的實現特定限制(即CLR和Mono VM)。

但是,問題是關於C而不是關於C的任何特定實現,而不是關於CLI的,因此我覺得聲明一個類可以實現的接口數量是無限的。

15

您可以實現的接口數量受編譯器可以處理的限制。太多的接口導致C#編譯器出現堆棧溢出異常(錯誤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());