39

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
}
Brian R. Bondy
  • 339,232
  • 124
  • 596
  • 636
  • 5
    While it's not possible in C#, it's possible in alternative .NET strongly-typed languages like [Boo](http://boo.codehaus.org/) and [Nemerle](http://nemerle.org/Main_Page). – Jordão Oct 26 '10 at 13:15
  • 1
    You can read the Metaprogramming in .NET http://www.manning.com/hazzard by Kevin Hazzard and Jason Bock – Matija Grcic Oct 15 '13 at 08:20
  • @Jordão: Boo is a very different language and Nemerle is more or less dead since Jetbrains hired the brains. Perhaps Script.NET is worth a mention. – david.pfx Jul 01 '16 at 00:49
  • try taking a look at [script.net](http://en.wikipedia.org/wiki/Script.NET); more info at --http://www.orbifold.net/default/?p=2457 – user309010 Apr 07 '10 at 05:43
  • sort of look for t4 templates Sorry on iphone and can't point to resource. Scott Hansleman posted last week about it. –  Oct 26 '08 at 06:01
  • You could do this with the new source generators feature – mhand Aug 30 '21 at 10:53

9 Answers9

39

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.

J D
  • 48,105
  • 13
  • 171
  • 274
36

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.

Community
  • 1
  • 1
Jacob Krall
  • 28,341
  • 6
  • 66
  • 76
8

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#.

Ira Baxter
  • 93,541
  • 22
  • 172
  • 341
  • 3
    -1: Good answer, but it doesn't answer this particular question. – John Saunders Feb 26 '10 at 18:57
  • 1
    @Saunders: Actually it does, but you have do some homework. If you want to implement the OP's specific task, you'll need to implement constant-folding program transformations and focus them on calls to your Fibonacci function. I note that you dinged my answer, when none of the answers addressed the OP's specific question either. – Ira Baxter Feb 26 '10 at 19:00
  • 1
    thanks, you pointed me in the right direction for something Im working on! – Ralph Willgoss Jun 18 '10 at 05:05
6

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" ;)

thAAAnos
  • 156
  • 3
5

No, metaprogramming is not possible in C#.

ryanyuyu
  • 6,366
  • 10
  • 48
  • 53
Brian
  • 117,631
  • 17
  • 236
  • 300
5

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.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • I know by experience that template code can be reused. And the so-called "language independence" you're referring to actually means you have to use a .net compliant language... There are limitations to both .net generics as well as c++ templates. But these are not the correct ones. – Benoît Feb 09 '09 at 11:23
  • And of course, you CAN write a complex number class (or better yet, a struct) in C#, but template libraries that do calculations on numeric type parameters are hard to write and use, see http://www.codeproject.com/KB/cs/genericnumerics.aspx and http://www.codeproject.com/KB/cross-platform/BenchmarkCppVsDotNet.aspx – Qwertie Oct 18 '11 at 17:18
  • "You can't write a std::complex class in C#". In what sense? – J D Feb 22 '12 at 10:36
  • 1
    @JonHarrop In the sense that performance will suck and you lose compile time safety too. And some parts related to conversion aren't possible at all. – CodesInChaos Feb 22 '12 at 10:49
  • @CodeInChaos: Why do you believe the performance will suck, what compile-time safety do you lose and which parts of the conversion aren't possible at all? – J D Feb 23 '12 at 09:18
  • 2
    1) There are no generic constraints for overloaded operators. Thus you lose compile-time safety. 2) Without those constrains no user defined operator can be chosen on specialization. Thus you need to use runtime method generations, and you get a delegate call overhead whenever you call an operator. 3) You can't express something like "if `T1` is implicitly convertible to `T2` then `Complex` should be implicitly convertible to `Complex`". – CodesInChaos Feb 23 '12 at 11:17
3

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.

piojo
  • 6,351
  • 1
  • 26
  • 36
3

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
}
JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • 3
    The questioner hasn't really specified what they mean by Metaprogramming, but I think it's safe to say that it's different to what you mean. – Anthony Jan 03 '09 at 17:12
  • 1
    @Anthony, the problem with ambiguous questions is they produce incorrect or not-intented answers. I could not answer the question or provide an answer which may answer the question. As long as I'm here, I figure I might as well answer :) – JaredPar Jan 03 '09 at 18:57
3

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

Özgür
  • 8,077
  • 2
  • 68
  • 66