Question

In particular, would it be possible to have code similar to this c++ code executed at compile time in 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
}
Was it helpful?

Solution

No, metaprogramming of this complexity is not supported directly by the C# language. However, like @littlegeek said, the Text Template Transformation Toolkit included with Visual Studio will allow you to achieve code generation of any complexity.

OTHER TIPS

Metaprogramming is possible in .NET (see compiler compilers, regular expressions, code DOM, reflection etc.) but C# is not capable of template metaprogramming because it does not have that language feature.

You must be carefull when talking about compile-time when dealing with Java or .Net languages. In those languages you can perform more powerfull metaprogamming (in the broader sense - reflection- ) than C++ due to the fact that "compilation time" (JIT) can be postponed after "run time" ;)

Most people insist on trying to metaprogram from inside their favorite language. That doesn't work if the language doesn't support metaprogramming well; other answers have observed that C# does not.

A way around this is to do metaprogramming from outside the language, using program transformation tools. Such tools can parse source code, and carry out arbitrary transformations on it (that's what metaprogramming does anyway) and then spit out the revised program.

If you have a general purpose program transformation system, that can parse arbitrary languages, you can then do metaprogramming on/with whatever language you like. See our DMS Software Reengineering Toolkit for such a tool, that have robust front ends for C, C++, Java, C#, COBOL, PHP and a number of other programming langauges, and has been used for metaprogramming on all of these.

DMS succeeds because it provides a regular method and support infrastructure for complete access to the program structure as ASTs, and in most cases additional data such a symbol tables, type information, control and data flow analysis, all necessary to do sophisticated program manipulation.

EDIT (in response to comment): One could apply DMS to implement the OP's task on C#.

No, metaprogramming is not possible in C#.

The essential difference between .NET Generics and C++ Templates is that generics are specialized at runtime. Templates are expanded at compile time. The dynamic behavior of generics makes things like Linq, expression trees, Type.MakeGenericType(), language independence and code re-use possible.

But there is a price, you can't for example use operators on values of the generic type argument. You can't write a std::complex class in C#. And no compile-time metaprogramming.

It is going to be possible. Watch Anders Hejlsberg's The Future of C# talk.

To a very limited extent, C# something that could be interpreted as meta-programming. But really it's nothing more than overload resolution. It's a real stretch to call it meta programming.

Example:

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
}

Not in the way you're asking, but you can use some of the old C++ tricks to generate classes whose traits are specified statically:

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];
    }
}

Using this, you could define spatial classes:

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

I use this technique in a library that has a lot of subclasses, where adding a new data member requires a lot of boilerplate.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top