39

特别是,是否有可能在编译时在 c# 中执行类似于此 c++ 代码的代码

template <int N>
struct Factorial 
{
    enum { value = N * Factorial<N - 1>::value };
};

template <>
struct Factorial<0> 
{
    enum { value = 1 };
};

// Factorial<4>::value == 24
// Factorial<0>::value == 1
void foo()
{
    int x = Factorial<4>::value; // == 24
    int y = Factorial<0>::value; // == 1
}
4

9 回答 9

35

不,C# 语言不直接支持这种复杂性的元编程。但是,就像@littlegeek所说,Visual Studio 中包含的文本模板转换工具包将允许您实现任何复杂性的代码生成。

于 2008-10-26T06:14:14.080 回答
34

在 .NET 中可以进行元编程(参见编译器编译器、正则表达式、代码 DOM、反射等),但 C# 不能进行模板元编程,因为它没有那种语言特性。

于 2012-02-22T10:42:50.610 回答
7

大多数人坚持尝试从他们最喜欢的语言内部进行元编程。如果语言不能很好地支持元编程,那就不行了。其他答案观察到 C# 没有。

解决此问题的一种方法是使用 程序转换工具从语言外部进行元编程。这样的工具可以解析源代码,并对其进行任意转换(这就是元编程所做的),然后吐出修改后的程序。

如果您有一个可以解析任意语言的通用程序转换系统,那么您可以使用/使用您喜欢的任何语言进行元编程。请参阅我们的DMS Software Reengineering Toolkit了解此类工具,该工具具有适用于 C、C++、Java、C#、COBOL、PHP 和许多其他编程语言的强大前端,并已用于所有这些语言的元编程。

DMS 之所以成功,是因为它提供了一种常规方法和支持基础设施,可以完全访问作为 AST 的程序结构,并且在大多数情况下,附加数据,如符号表、类型信息、控制和数据流分析,都是执行复杂程序操作所必需的。

编辑(回应评论):可以应用 DMS 在 C# 上实现 OP 的任务。

于 2010-02-26T18:19:38.550 回答
6

在处理 Java 或 .Net 语言时谈论编译时必须小心。在这些语言中,由于“编译时间”(JIT)可以在“运行时间”之后推迟,因此您可以执行比 C++ 更强大的元编程(广义上的反射);)

于 2008-11-11T14:42:18.147 回答
5

不,元编程在 C# 中是不可能的。

于 2008-10-26T01:25:43.443 回答
5

.NET 泛型和 C++ 模板之间的本质区别在于泛型在运行时是专用的。模板在编译时展开。泛型的动态行为使诸如 Linq、表达式树、Type.MakeGenericType()、语言独立性和代码重用之类的东西成为可能。

但是这是有代价的,例如,您不能对泛型类型参数的值使用运算符。您不能在 C# 中编写 std::complex 类。并且没有编译时元编程。

于 2008-10-26T14:39:14.340 回答
3

非常有限的程度上,C# 可以解释为元编程。但实际上它只不过是重载决议。将其称为元编程是一个真正的延伸。

例子:

static string SomeFunc<T>(T value) {
    return "Generic";
}
static string SomeFunc(int value) {
    return "Non-Generic";
}

static void Example() {
    SomeFunc(42);           // Non-Generic
    SomeFunc((object)42);   // Generic
}
于 2008-10-26T03:54:19.417 回答
3

这将是可能的。观看 Anders Hejlsberg 的 The Future of C#演讲。

于 2009-01-03T16:33:32.947 回答
3

不是按照您要求的方式,但是您可以使用一些旧的 C++ 技巧来生成静态指定特征的类:

abstract class Integer
{
    public abstract int Get { get; }
}

public class One : Integer { public override int Get { return 1; } } }
public class Two : Integer { public override int Get { return 2; } } }
public class Three : Integer { public override int Get { return 3; } } }

public class FixedStorage<T, N> where N : Integer, new()
{
    T[] storage;
    public FixedStorage()
    {
        storage = new T[new N().Get];
    }
    public T Get(int i)
    {
        return storage[i];
    }
}

使用它,您可以定义空间类:

public class Vector3 : FixedStorage<float, Three> {}
public class Vector2 : FixedStorage<float, Two> {}
public class GridCell : FixedStorage<int, Two> {}

我在一个有很多子类的库中使用这种技术,其中添加一个新的数据成员需要很多样板文件。

于 2013-11-12T09:00:41.223 回答