10

C# unfortunately does not allow for extra user-defined syntax. But I was wondering whether it was possible to surpass this limitation by tapping into the visual studio onbuild-event.

Suppose I have some syntactic sugar which could be easily translated into actual C# code. If I were to automatically translate a cs document containing this new syntax into a valid cs document, right before a C#-project is built, then the project could build succesfully. Overall this would function as if I had extended the C# language, because I started with an invalid cs document containing unoffical syntax, but it compiled anyway.

I realize that this has a few problems, such as that this translation is permanent. This could perhaps be circumvented by restoring the original cs(which should be restored after the debugging has ended, otherwise some IDE functionality would be lost). But these are secondary problems.

Please let me know what you think of this idea. Is this possible, and if so, could someone direct me to some useful tutorials so achieve this? In specific the tapping-into-a-onbuild-event. I've searched MSDN, but the topic(http://msdn.microsoft.com/en-us/library/hthab0h8.aspx) didn't help me.

JBSnorro
  • 6,048
  • 3
  • 41
  • 62
  • This is not a good idea. – Steven Sudit Oct 20 '10 at 20:13
  • Curious, do you have an example of what kind of syntax you would define? When creating a kind of domain specific language in C# I generally write tons of extension methods and use good old lambda syntax to chain my language elements together to form coherent sentence-like structures in the code. – David Oct 20 '10 at 20:18
  • @Steven: While I generally agree, one has to remember that, if a certain Dane would have thought so 30 years ago, C#'s ancestor would never have been invented. `:)` – sbi Oct 20 '10 at 20:18
  • 2
    @sbi: I suspect that JBSnorro is no Bjarne Stroustrup. – Steven Sudit Oct 20 '10 at 20:19
  • This is how Ratfor, a predecessor to C, was done. I've used FORTRAN 77 compilers that were C compilers with f2c as a preparatory step. There's precedents for this. – David Thornley Oct 20 '10 at 20:26
  • I'm pretty sure Spec# did(or at least could do) exactly that. Translate the specs# files into plain C# which then compile. – CodesInChaos Oct 20 '10 at 20:27
  • @ David: For example I could define $"My name is $Name and I am $Age years old." to be equal to StringBuilder ("My name is ").Append (Name.ToString ()).Append (" and I am ").Append (Age.ToString ()).Append (" years old.").ToString () And i'm sure there are many more useful applications I can't come up with right now. And @ Steven: I think extending a language is a good idea(although maybe not in this way). If extending a language would not be a good idea, why is there a C# 2.0, C# 3.0, C# 3.5 and C# 4.0 ? – JBSnorro Oct 20 '10 at 20:28
  • 2
    @JBSnorro: I still have nightmares of what people used to do with C++ macros. –  Oct 20 '10 at 20:33
  • 1
    I mean, it's great that C# gets extended, but it's not a power that belongs in the hands of the average developer. –  Oct 20 '10 at 20:34
  • @Steven: You do have a point there, and that's why I said I generally agree with your sentiment. (It's a bit like operator overloading in C++: You're supposed to not to misuse operators for doing things that are not obvious. But that's exactly what was done to the shift operators for streaming and addition for strings...) – sbi Oct 20 '10 at 20:36
  • @JBSnorro: You do know that you could do `string.Format("My name is {0} and I am {1} years old.", Name, Age)`, don't you? – sbi Oct 20 '10 at 20:38
  • @Steven : lol... I'm trying to imagine Bjarne's exploratory S.O. question now :P – Andrew Barber Oct 20 '10 at 20:41
  • Okay, my example may have had another trivial solution.. fine.. But i still don't see why you would oppose to this idea if I had some syntax which could really smooth up coding – JBSnorro Oct 20 '10 at 20:43
  • @sbi: Or define a string extension to allow `"Replace this: {0}".FormatWith(42)`. – Steven Sudit Oct 20 '10 at 20:44
  • I would suggest that providing your own syntax would, in the vast majority of cases, be the wrong thing to do. However, it's still a very interesting idea. – Josh Smeaton Oct 20 '10 at 21:14
  • 2
    Okay, to sum it up: generally the idea is bad, unless some syntax is a real improvement, which is rare/hard. But at least I've learned that it is possible, constrasting my previous understanding. – JBSnorro Oct 21 '10 at 11:53

3 Answers3

11

I won't say whether this is a good idea or not, since I don't know enough about what you're trying to do. I would suggest this, though: What you're proposing is to have some kind of "extended C#" source code file that gets translated into regular cs during the build process.

Personally, I would clarify this by first breaking away from the idea that you are "extending" the C# language; I would instead think of it as defining a new language that happens to be syntactically similar to C# (I assume). Use a different file extension so that Visual Studio does not try to compile your language as C#. (Maybe .csx? People love adding the letter x, right?)

Visual Studio already does this sort of thing in other ways that might not be quite so obvious. If you add a resource file to a project, Visual Studio will typically also include a dynamically generated "designer.cs" with code generated based on the content of your .resx file. If you look at the properties of the .resx file, you'll note that the "Custom Tool" property has a value of "ResXFileCodeGenerator". In theory you should be able to implement your own generator to perform the translation step that you mentioned. In fact, this translation does not have to be a one-time thing as you said. The translation process should generate a new file, but leave the original file intact. Any changes to the original file causes Visual Studio to regenerate the auto-generated file.

I've not tried to implement a custom generator myself, but I think these articles are relevant: Implementing Single File Generators, and Registering Single File Generators

Your .csproj file would contain something such as the following:

<Content Include="Example.csx">
  <Generator>ExtendedCSharpCodeGenerator</Generator>
  <LastGenOutput>Example.cs</LastGenOutput>
</Content>
<Compile Include="Example.cs">
  <AutoGen>True</AutoGen>
  <DesignTime>True</DesignTime>
  <DependentUpon>Example.csx</DependentUpon>
</Compile>

Where Example.csx is the source code file containing your extended syntax and Example.cs is the resulting output of translating Example.csx into normal C# code.

Dr. Wily's Apprentice
  • 10,212
  • 1
  • 25
  • 27
  • Perfect, that is precisely what I had been looking for today, specifically, the dynamically generated node-cs's in the solution explorer. Thank you. Ik hope the links you provided will get me there :P – JBSnorro Oct 20 '10 at 20:48
  • Aha! This is why I love stackoverflow. :) Just what I was looking for. +1! – Robin Maben Nov 22 '10 at 05:46
3

What you are talking about doing seems like a perfect task for T4 templates in Visual Studio.

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

You can define anything you'd like; text files with a certain format, UML models, a database; and your T4 template can transform it into code in what ever way you wish.

Andrew Barber
  • 39,603
  • 20
  • 94
  • 123
  • Yes, I had already looked into that, but I found it inconvenient, since it can only create entire documents, while I prefer a 'mostly regular' cs document with occasionally some deviating syntax. – JBSnorro Oct 20 '10 at 20:55
  • Your understanding of how it works is not entirely correct. It can be used to edit existing source code, as well. For example, in the ASP.NET MVC Contrib T4 template, existing `Controller` classes have their base class altered and their methods changed to `Virtual` in order to inherit the generated code. – Andrew Barber Oct 20 '10 at 21:23
2

I'm not sure it's a good idea, but I just had an idea: maybe you can have a look at Extending Visual Studio, download the SDK and check the doc. Maybe it would be possible to do what you are trying to achieve.

Sauleil
  • 2,573
  • 1
  • 24
  • 27