2016-03-12 98 views
7

如果我實現了一個冒用許多類型參數實例化的泛型類型,我是否應該避免(對於JIT性能/代碼大小等原因)有許多嵌套的非泛型類型?我應該避免泛型類型中的嵌套類型嗎?

實施例:

public class MyGenericType<TKey, TValue> 
{ 
    private struct IndexThing 
    { 
     int row; int col; 
    } 

    private struct SomeOtherHelper 
    { 
     .. 
    } 

    private struct Enumerator : IEnumerator<KeyValuePair<TKey, TValue>> { } 

} 

這同樣適用是有外部的非通用的類型,但接着就污染的命名空間的替代方案。 是否有最佳做法?

public class MyGenericType<TKey, TValue> 
{ 
    private struct Enumerator : IEnumerator<KeyValuePair<TKey, TValue>> { } 
} 

internal struct IndexThingForMyGenericType 
{ 
    int row; int col; 
} 

internal struct SomeOtherHelper 
{ 
    ... 
} 
+0

一如既往的永不優化,永遠不會遇到瓶頸。只是代碼的方式是最有意義的,主要是它不會是一個問題。關於這個問題,我不知道,但是你可以在BCL中看到很多嵌套的私人班,所以我不介意從設計的角度來看這條路線。如你所說第二個可能會令人困惑 – nawfal

+0

這段代碼在語義上並不相同。在你的第一個例子中,SomeOtherHelper不是單一類型,因爲它取決於泛型參數。例如,'typeof(MyGenericType .SomeOtherHelper)'與'typeof(MyGenericType .SomeOtherHelper)'不同。 – Enigmativity

+0

如果您的問題是讓名稱空間中的類因爲您希望它更清潔,請將其添加到子名稱空間,如果您的名稱空間是MyNamespace,那麼將它添加到MyNamespace.AccesoryNamespace。 – Gusman

回答

6

在C#中,泛型類型的每個嵌套類型都是固有泛型的。編譯器會使嵌套類型也是通用的(不知道)。有關更多信息,請參閱this article

雖然泛型分享參考類型的JIT代碼,如this interview中所述,但與非泛型類相比,它有一些開銷。每個值類型都有自己的JIT代碼。

  • 如果類型僅使用泛型類--IT更有意義的是私人嵌套類型。

  • 如果類型在其他地方使用,那麼它理想情況下應該是非嵌套類型(作爲內部)。

也就是說,如果你的嵌套類型不使用類型參數T在這種情況下,它並不需要是一個嵌套類型泛型類型,因此它成爲一個通用型爲好。

大多數情況下它應該沒關係,但如果您擔心在運行時創建的許多類型,則可以重構泛型類型以使非泛型基類充當嵌套類型的容器類型,並且將嵌套類型暴露爲受保護的。

public class NonGenericBase 
{ 
    protected struct IndexThing 
    { 
     int row; int col; 
    } 

    protected struct SomeOtherHelper 
    { 
     .. 
    } 
} 

public class MyGenericType<TKey, TValue> : NonGenericBase 
{ 
    private struct Enumerator : IEnumerator<KeyValuePair<TKey, TValue>> { } 

} 

這樣你就可以共享相同的嵌套類型。無運行時間開銷。每種類型參數都沒有單獨的類型。現在typeof(MyGenericType<int, string>.SomeOtherHelper)將等於typeof(MyGenericType<long, bool>.SomeOtherHelper)

+0

我認爲非泛型基類可能是要走的路。唯一不好的是,如果它實際上並不實用,它仍然必須(至少)像我的泛型一樣公開,所以現在我污染了公共API,而不僅僅是內部的一個:( 我仍然認爲這是儘管最壞的解決方案,謝謝 –

1

雖然這並不能完全回答這個問題,注意,引用類型的代碼是共享的,因爲在內部它是所有關於指針。所以你不必擔心代碼庫的膨脹。引自this回答(Anders Hejlsberg是quotee)。

現在,我們然後做是對所有類型的實例是價值 類型,如List<int>List<long>List<double>List<float> - 我們創建可執行本地代碼的唯一副本。因此List<int>得到 它自己的代碼。 List<long>獲取自己的代碼。 List<float>獲取自己的 代碼。 對於所有參考類型,我們共享代碼,因爲它們是 在代表性上是相同的。這只是指針。

+0

是的,但它甚至沒有共享相同大小的值類型,所以'MyGenericType .IndexThing' afaik。將不會重用MyGenericType DateTime,longIndexThing等等。對於2+類型參數,即使所有參考實例共享代碼,我仍然擔心組合爆炸! –

+0

@AndersForsgren是的,我知道。這就是爲什麼我說它是共享*參考*類型。 – Kapol