C#中的泛型是否与C ++中的相同?

时间:2013-03-22 05:18:15

标签: c# c++ generics

我知道在C ++中,泛型实际上并不存在,但您可以使用template来模拟它。构建代码时,编译器预处理代码并生成一个新代码,其中通用值替换为对象声明中指定的实际值,然后是真正编译的新代码。例如,假设我们有类A,如下所示:

template<class T>
class A
{
    T f();
};

然后我们在A<int> a;代码中的其他位置。编译的实际代码是:

class A
{
    //Replaces T by int in the pre-processing
    int f();
};

在整个介绍之后,让我们谈谈。

我的问题是:

  • C#是否像C ++一样对待泛型?如果没有,那怎么样?
  • 他们是特殊类型吗?
  • 它们是在运行时还是在编译时解决?
  • 激活寄存器中的泛型类型预留了多少空间?

3 个答案:

答案 0 :(得分:6)

这是一个非常广泛的主题,可以通过以下方式更好地解释:

http://msdn.microsoft.com/en-us/library/c6cyy67b.aspx

要sumarize(来自上面链接的MSDN文章):

  • C#泛型不提供与C ++相同的灵活性 模板。例如,无法调用算术 C#泛型类中的运算符,尽管可以调用用户 定义的运算符。

  • C#不允许非类型模板参数,例如模板 C {}。

  • C#不支持显式专业化;也就是习俗 实现特定类型的模板。

  • C#不支持部分专业化:自定义实现 对于类型参数的子集。

  • C#不允许将type参数用作基类 通用类型。

  • C#不允许类型参数具有默认类型。

  • 在C#中,泛型类型参数本身不能是通用的 构造类型可以用作泛型。 C ++确实允许模板 参数。

  • C ++允许代码可能对所有类型参数无效 模板,然后检查用作的特定类型 类型参数。 C#要求类中的代码以这样的方式编写 它将适用于任何满足约束的类型。 例如,在C ++中,可以编写一个使用该函数的函数 算术运算符+和 - 在类型参数的对象上,其中 将在模板实例化时产生错误 使用不支持这些运算符的类型。 C#不允许这样做; 允许的唯一语言结构是可以推导出的结构 来自约束。

一般来说,虽然它们在大多数情况下都有相似的语法和用法,但在使用和功能方面存在很多差异。

答案 1 :(得分:3)

对于如何解析C ++模板存在误解。在C ++中,模板被处理两次(注意:术语“预处理”保留给预处理器,完全与模板无关)。

在第一个处理时间,解析非依赖名称,而未解析依赖名称:

int x;

template <typename T> foo() {
    x;    // <-- resolved in phase 1
    T::x; // resolved in phase 2, depends on "T"
}

在实例化时输入阶段2。 E.g:

struct Frob {
    int x;
};

int main () {
    foo<Frob>();
} // <-- instantiation happens right before the '}'

此外,C ++模板在每个函数的基础上延迟实例化。这意味着并非类模板中的所有内容都必须是可解析的。仅实例化实际使用的函数,这意味着仅为使用的成员函数输入阶段2。

这使得模板比C#样式泛型更通用:当您实例化类模板时,实例化类型只需要支持模板的子集。

在C#中,泛型得到了热切的解决。 “实例化”类型必须支持所有通用类仅可能使用,这对通用性提出了相当严格的限制。

你已经知道,但两者都是截然不同的概念。泛型是一个运行时构造,使用反射和自修改代码,C#语言必须非常防御w.r.t.可分解。模板是一个编译时构造(注意:不是_preprocessing构造!),支持Turing-complete元编程,包括类型和非类型参数以及eager和lazy实例化之间的强大折衷。

两者都有自己的特色。

答案 2 :(得分:1)

.NET泛型的实现是一种混合。

当泛型类编译成MSIL时,它被编译成单个泛型类型定义。

当客户端使用泛型类时,.NET运行时为简单类型参数(bool,int等)编译类的机器代码的单独副本,但不为不同的对象类型生成单独的代码。他们都共享Object的代码。