【问题标题】:Are generics in C# treated the same way as in C++? [duplicate]C# 中的泛型是否与 C++ 中的处理方式相同? [复制]
【发布时间】:2013-03-11 21:21:36
【问题描述】:

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

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

然后在代码的其他地方我们有A&lt;int&gt; a;。实际编译的代码是:

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

在整个介绍之后,让我们进入正题。

我的问题是:

  • C# 对泛型的处理方式与 C++ 相同吗?如果没有,那怎么办?
  • 它们是特殊类型吗?
  • 它们是在运行时还是在编译时解决的?
  • 在激活寄存器中为泛型类型保留了多少空间?

【问题讨论】:

标签: c# c++ generics


【解决方案1】:

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

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

总结(来自上面链接的 MSDN 文章):

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

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

  • C# 不支持显式特化;也就是风俗 为特定类型实现模板。

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

  • C# 不允许将类型参数用作 泛型类型。

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

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

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

一般来说,虽然它们在大多数情况下共享相似的语法和用途,但在用法和功能上存在许多很大的差异。

【讨论】:

【解决方案2】:

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

在第一次处理时,非依赖名称被解析,而依赖名称不被解析:

int x;

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

在实例化时进入阶段 2。例如:

struct Frob {
    int x;
};

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

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

这使得模板比 C# 风格的泛型更通用:当你实例化一个类模板时,实例化的类型只需要支持模板的一个子集。

在 C# 中,泛型被急切地解决。 “实例化”类型必须支持泛型类仅可能使用的所有内容,这对多功能性提出了相当严格的限制。

您已经知道了,但两者确实是截然不同的概念。泛型是一种运行时构造,并且具有反射和自修改代码,C# 语言必须非常具有防御性 w.r.t。可解决性。模板是一种编译时构造(注意:不是 _preprocessing 构造!),支持具有类型和非类型参数的图灵完备的元编程,以及在急切和惰性实例化之间的强大折衷。

两者各有特点。

【讨论】:

  • 感谢您澄清 C++ 中如何处理模板;)
【解决方案3】:

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

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

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

【讨论】:

    猜你喜欢
    • 2011-07-02
    • 1970-01-01
    • 2011-08-25
    • 1970-01-01
    • 2021-10-12
    • 2012-05-08
    • 2016-03-25
    • 1970-01-01
    相关资源
    最近更新 更多