簡體   English   中英

C#:泛型類中的嵌套類是否應該被認為是通用的?

[英]C#: Should a nested class in a generic class be considered generic?

namespace GenericsTest
{
    public class AGenericClass<T>
    {
        public class NestedNonGenericClass
        {
        }
    }
}

在上面的例子中, NestedNonGenericClass應該被視為泛型類嗎?

反射API說它是一個泛型類,甚至把包含類的模板參數作為嵌套類的模板參數。

Type nestedClass = typeof(AGenericClass<int>.NestedNonGenericClass);
Console.Out.WriteLine("IsGeneric: {0}\tHasGenericArguments: {1}", 
   nestedClass.IsGenericType, nestedClass.GetGenericArguments().Length > 0);

打印出:

IsGeneric:True HasGenericArguments:True

我不完全同意這種行為。 即使編譯器為NestedNonGenericClass生成泛型類型,我也想知道它是否是泛型的,因為它是聲明的,或者因為它的容器是通用的。

所以,我的問題是:

首先,你認為可以考慮嵌套類泛型,因為它的容器是通用的嗎? 為什么/為什么不呢?

其次,您是否碰巧知道其他一些API可以幫助我只識別聲明為通用的類?

PS:我在ECMA規范中找不到與此相關的任何內容(或者我可能只是掩蓋它)。

- 編輯 -

為了添加更多的上下文,我正在開發一種代碼生成器。 我正在使用反射API來確定類型是否是通用的。

我遇到了Dictionary<TKey, TValue>.KeyCollection

對於KeyCollection ,反射API表示它是通用的,並將我交給容器中聲明的TKeyTValue 因此,生成器最終生成Dictionary<TKey, TValue>.KeyCollection<Tkey, TValue>

我能解決這個問題的唯一方法是將嵌套類的模板參數與容器匹配,並消除所有匹配的模板參數。 但我想知道是否有更好的方法。

簡而言之,是 - 一個類型從包含它的任何類型繼承類型參數:這是List<T>.Enumerator和許多其他場景等的關鍵 - 它們與外層類共享T是至關重要的(不只是任何T )。

ECMA參考文獻是§25.1:

嵌套在泛型類聲明或泛型結構聲明(第25.2節)中的任何類本身都是泛型類聲明,因為應提供包含類型的類型參數以創建構造類型。

是的,您的嵌套類絕對是通用的,因為T綁定到嵌套類的任何實例范圍內的類型(這稱為封閉泛型 )。

using System;
using System.Collections.Generic;

public class AGenericClass<T> {
    public class NestedNonGenericClass {
        public void DoSomething() {
            Console.WriteLine("typeof(T) == " + typeof(T));
        }
    }
}

public class MyClass {
    public static void Main()   {
        var c = new AGenericClass<int>.NestedNonGenericClass();
        var d = new AGenericClass<DateTime>.NestedNonGenericClass();
        c.DoSomething();
        d.DoSomething();
        Console.ReadKey(false); 
    }

}

同樣的DoSomething()方法根據泛型類型的關閉方式產生不同的輸出 - 所以是的,內部類肯定表現出通用行為。

如果你不打算在NestedNonGenericClass中使用T,你可以將它放在類之外並使其成為私有..那么它就不會是Generic ....

我選擇理解它的方式是,當你使用泛型類型時,C#會生成該類型的所有內容。 實際上,如果我想象一下如果我使用上面例子中的AGenericClass和AGenericClass會產生什么,那么你最終會得到兩個嵌套類的副本:

public class AGenericClass<int>
{
    public class NestedNonGenericClass
    {
    }
}

public class AGenericClass<float>
{
    public class NestedNonGenericClass
    {
    }
}

因此,我認為嵌套類是泛型類,因為它有兩個版本,一個叫做AGenericClass <int> .NestedNonGenericClass,另一個叫做AGenericClass <float> .NestedNonGenericClass。 實際上,就像你明確指定嵌套類也是通用類一樣。 如果您希望嵌套類適應泛型類型,則此行為非常有用。

但是,我發現我不能再以與普通類相同的方式使用嵌套類了。 我不記得確切的例子了,我很抱歉,但是我知道,一旦我不得不將一個類移出一個泛型,以便我可以按照預期從代碼中的其他地方使用它。 它違背了我一直用於嵌套類的常用模式,因此我不喜歡它,但這是唯一的方法。 所以我可以理解你是否可能不同意這樣做的方式,但說實話,我認為它的方式是最清晰的方式。 我的意思是,對於您和編譯器來說,如果您將嵌套類移到外部並將其作為常規類,那么您不希望編譯器將其生成為泛型。 我不認為他們可以改善這一點。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM