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: 真
我不完全同意这种行为。即使编译器为NestedNonGenericClass
生成泛型类型,我也想知道它是否是通用的,因为它是声明的,或者因为它的容器是通用的。
所以,我的问题是:
首先,您是否认为可以考虑嵌套类通用,因为它的容器是通用的?为什么/为什么不呢?
其次,您是否碰巧知道其他一些API可以帮助我只识别声明为通用的类?
P.S:我在ECMA规范中找不到与此相关的任何内容(或者我可能只是掩饰了它)。
- 编辑 -
要添加更多上下文,我正在开发一种代码生成器。我正在使用反射API来确定类型是否是通用的。
我遇到了Dictionary<TKey, TValue>.KeyCollection
的问题。
对于KeyCollection
,反射API表示它是通用的,并将我交给容器中声明的TKey
和TValue
。因此,生成器最终会生成Dictionary<TKey, TValue>.KeyCollection<Tkey, TValue>
我能解决这个问题的唯一方法是将嵌套类的模板参数与容器匹配,并消除所有匹配的参数。但我想知道是否有更好的方法。
答案 0 :(得分:19)
简而言之,是的 - 一个类型从包含它的任何类型继承类型参数:这是List<T>.Enumerator
和许多其他场景等的关键 - 它们共享{{1来自外部类(不只是任何T
)。
ECMA ref是§25.1:
任何嵌套在泛型内的类 类声明或通用结构 声明(第25.2节)本身就是一个 泛型类声明,因为类型 包含类型的参数 应提供以创建一个 构造类型。
答案 1 :(得分:6)
是的,您的嵌套类绝对是通用的,因为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()
方法产生不同的输出,具体取决于泛型类型的关闭方式 - 所以是的,内部类肯定表现出通用行为。
答案 2 :(得分:2)
如果您不打算在NestedNonGenericClass中使用T,您可以将它放在类之外并将其设置为私有..那么它就不会是Generic ....
答案 3 :(得分:2)
我选择理解它的方式是,当您使用泛型类型时,C#会生成该类型的所有内容。实际上,如果我想象一下如果我使用上面例子中的AGenericClass和AGenericClass会产生什么,那么你最终会得到两个嵌套类的副本:
public class AGenericClass<int>
{
public class NestedNonGenericClass
{
}
}
public class AGenericClass<float>
{
public class NestedNonGenericClass
{
}
}
因此,我认为嵌套类是泛型类,因为它有两个版本,一个叫做AGenericClass&lt; int&gt; .NestedNonGenericClass,另一个叫做AGenericClass&lt; float&gt; .NestedNonGenericClass。实际上,就像你明确指定嵌套类也是通用类一样。如果您希望嵌套类适应泛型类型,则此行为非常有用。
但是,我发现我不能再以与普通类相同的方式使用嵌套类了。我不记得确切的例子了,我很抱歉,但是我知道,一旦我不得不将一个类移出一个泛型,以便我可以按照预期从代码中的其他地方使用它。它违背了我一直用于嵌套类的常用模式,因此我不喜欢它,但这是唯一的方法。所以我可以理解你是否可能不同意这样做的方式,但说实话,我认为它的方式是最清晰的方式。我的意思是,对于您和编译器来说,如果您将嵌套类移到外部并将其作为常规类,那么您不希望编译器将其生成为泛型。我不认为他们可以改善这一点。