在 C# 4.0 中,是不是可以从泛型类型参数派生类?
Posted
技术标签:
【中文标题】在 C# 4.0 中,是不是可以从泛型类型参数派生类?【英文标题】:In C# 4.0, is it possible to derive a class from a generic type parameter?在 C# 4.0 中,是否可以从泛型类型参数派生类? 【发布时间】:2011-08-18 22:20:39 【问题描述】:我一直在尝试这个,但我似乎无法弄清楚这一点。我想做这个……
public abstract class SingletonType<TSingleton, TBaseClass> : TBaseClass
where TSingleton : TBaseClass, new()
where TBaseClass : class
static TSingleton _singleton;
public static TSingleton Singleton
=> _singleton ?? (_singleton = new TSingleton());
计划是像这样使用它,将单例模式“包装”在基类周围...
public class SingletonFoo : SingletonType<SingletonFoo, Foo>
但是,我不断收到这个
不能从 'TBaseClass' 派生,因为它是一个类型参数
嗯...我认为类型正是您所做的派生的!
那么我错过了什么?
注意:这当然是一个简单的例子,因为它没有添加任何有用的东西,但假设 SingletonType
有很多与问题无关的其他逻辑,因此它被省略了专注于手头的问题。
【问题讨论】:
你说,“嗯......我认为类型正是你所衍生的!” — 是的,但请再次阅读消息。它说“类型参数”,不是“类型”。这是不同的。 然而,您可以在使用类型的泛型中的任何地方使用该“类型参数”(例如“公共静态 T”),那么如何以我想要的方式使用它与使用它作为返回不同类型? (到目前为止,@Tejs 似乎最有洞察力。) 可能值得注意的是,与继承相反,组合在这里更为理想。 @Mohamed Nuur,想详细说明一下吗? (......或者任何人都可以?)不知道你的意思。 Why cannot C# generics derive from one of the generic type parameters like they can in C++ templates?的可能重复 【参考方案1】:C# 中的泛型类型不是 C++ 模板;请记住,泛型类型必须适用于所有可能的类型参数。模板只需要适用于您实际制作的结构。
这个问题是重复的;看我的回答
Why cannot C# generics derive from one of the generic type parameters like they can in C++ templates?
有关此的更多想法。基本上,简短的回答是,可观的成本并没有超过该功能的小好处。如果您不喜欢该答案,请参阅我的第二个答案:
Why cannot C# generics derive from one of the generic type parameters like they can in C++ templates?
如果您也不喜欢这个答案,请查看后续问题:
What are the good reasons to wish that .NET generics could inherit one of the generic parameter types?
【讨论】:
【参考方案2】:不,这是不可能的。例如,采用声明为sealed
的类型。您不能从该类继承,并且没有限制非密封类型的限制,因此尝试通过泛型参数从它继承是不可能的。
【讨论】:
好吧,这并不能真正解释原因——编译器可能只是不允许使用MyType<X>
,其中X
是密封类型,而不是完全禁止声明MyType<T> : T
。但当然答案仍然是“不可能”:)
好吧,为什么泛型参数必须对所有允许的类型都有效;例如,new()
约束允许您编写T sample = new T()
,因为否则您的通用参数可能是int
,这不是有效代码。如果没有nosealed
约束,继承带有密封的东西将违反 C# 规范。因为不是所有情况都对一个类型有效,并且不存在约束,所以它是无效的。错误消息是编译器不允许这种情况发生 =D
不,肤浅的原因是规范说基本类型不能是类型参数,句号。您试图提供的深层原因是规范以这种方式编写的原因。您对此提供了一个非解释。
(顺便说一句,int
确实有一个默认构造函数,因此满足 new()
约束,所有值类型也是如此。)跨度>
@MarqueIV:你的评论毫无意义。没有object
约束。也许你的意思是class
,但是你的评论是错误的:你可以有一个new()
没有class
约束。【参考方案3】:
每个类型都有 1 个真实的、离散的父类,即使涉及泛型也是如此。即使在处理开放的泛型类型(例如,typeof(List<>)
)时,您仍然可以找到父类。
如果你想要的东西被允许,这将是不正确的,typeof(SingletonType<,>
将没有父类型,这是不允许的。
【讨论】:
【参考方案4】:不,这是不可能的,因为假设你有这个类:
class bar
int example = 0;
现在这是我们的类型参数类:
class foo<T> : T
int example = 5;
如果我们创建了foo<bar>
类型的变量,那么example
就会混淆。
【讨论】:
怎么会混在一起呢? ‘Bar’ 有一个类型参数,而不是基类。它们完全不相关,而且范围不同。 @MarqueIV 不,因为T
是bar
的foo<bar>
的一种。由于foo
类继承自T
类(bar
),因此example
可以是0
或5
。
很抱歉,这是不正确的。它们的范围完全不同。您可以从泛型实例访问一个示例,而从泛型中通过 T 定义的任何实例变量访问另一个示例。它们不是一回事。
您似乎不明白继承在 C# 中是如何工作的。 example
在bar
中是私有的,因此来自bar
的派生类可以毫无问题地声明自己的example
。即使example
不是私有的,那么foo<T>
的example
也会被视为new
。
哦,我明白了,打扰了以上是关于在 C# 4.0 中,是不是可以从泛型类型参数派生类?的主要内容,如果未能解决你的问题,请参考以下文章