1/ I haven't mentioned much about C# integration into Visual Studio yet, but at the same time we were working on creating a new language, a new runtime, and a new framework we also decided to take disparate shells (MSDEV, devenv, VB6) and combine them. This was… a lot.
2/ As you might expect, taking on so much at the same time meant a very long development cycle. For those folks using VS6 it was a long wait for VS7 (‘98 to ’02). Regardless, we wanted to continue to provide a compelling LOB (line of business) client app framework while also
3/ enabling web apps (via ASP.NET, web forms/services, etc.). The client app framework manifested as Windows Forms and was the next iteration of a RAD app creation environment. The Windows Forms designer is extremely rich and intended to make developing UI-rich
4/ Windows apps faster and easier like the Ruby designer did in VB6. Unlike the VB6 designer, the Windows Forms designer needed to work across many languages, initially VB and C#, but ultimately including Delphi, Cobol, C++, F#, etc. This required the designer to read and
5/ generate source code in the language being developed. This was enabled through language-specific CodeDOM generators and parsers. Interestingly, the C# team did not own the CodeDOM implementation for C#. The framework team developed it. However, they only developed the CodeDOM
6/ generator (no parser). This was a priority as it was necessary for ASP.NET development (ASP.NET enabled code compilation on the server, and CodeDOM was the way that happened). That left the Windows Forms designer team in a bit of a lurch,
7/ because while we could use the CodeDOM to generate InitializeComponent code, there was nothing that enabled reading that code back and rendering the form. VB similarly had only a CodeDOM generator and had the same problem. There simply wasn’t time or resources to implement a
8/ full CodeDOM parser implementation, so instead, the C# and WinForms team developed a hack. The designer would query a *CodeModel* implementation for a specific private interface called IMethodXML. It would do this for the InitializeComponent method of any class that was
9/ ‘designable’. This interface would convert a very limited set of statements and expressions into XML that the designer would read and turn into its CodeDOM representation. As a simple example:
10/ This was put together on a weekend and was both awesome and problematic. It was awesome because it unblocked the designer and ultimately everyone that developed Windows Forms applications in VS 2002 using C# & VB. It was problematic for a few reasons.
11/ First, most of the team didn’t know it existed, including the test team. Second, it wasn’t documented. Third, it wasn’t the way the designer worked for other languages. Finally, since the schema was so limited it meant that as soon as a user made changes to the
12/ InitializeComponent method by hand, they could easily cause this method to choke, which in VS 2002 often led to the deletion of the body of the IntializeComponent method. That is, all the control and form placement, sizing, event hookup, etc. This was infuriating for
13/ developers and mitigated only slightly with a region we wrapped the method in saying something akin to ‘Designer generated code, don’t edit by hand’. There were other issues as well in that it was verbose, synchronous, language-specific, etc. That there was a designer
14/ experience at all for C#/VB was heroic but looking back on this one still gives me heartburn when thinking about the folks that lost hours/days/weeks of time when the designer ate their code. This ultimately led to some innovation in the languages ala partial classes and was
15/ part of the impetus to have a much richer code model in future versions.
• • •
Missing some Tweet in this thread? You can try to
force a refresh
1/ @werat asked about whether the debugger was using the C# compiler or language service in VS 2002. It was not. The debugger has a component called an ‘expression evaluator’ that is provided per language and is responsible for parsing and evaluating expressions when stopped at a
2/ breakpoint. For example, if you type into the immediate window, hover over a variable, type into the watch window, etc. the expression evaluator is involved. The debugger and the language service are actually deeply integrated in a number of scenarios in VS, which may
3/ initially seem surprising. I may talk about more of these scenarios in the future, but to give a flavor, when you set a breakpoint at design time the language service is involved, when you are using Edit and Continue the LS is involved, the range of what is being evaluated
1/ An interesting bit of history for .NET and C# is that there used to be a public System.Variant type. It was actually a keyword in C# for a while, alongside of object. If you’re unfamiliar with variants, they are a tagged union type.
2/ This means that they can represent many different data types and contain a ‘tag’ (a small enumeration) that defines the type of data they hold. This evolved because COM uses variants heavily, as did VB6 (and many other languages).
3/ In the original iterations of VB.NET, Variant was used for any untyped declaration (e.g. Dim a, b). Variants and System.Object are similar in some ways, and as you might guess, this led to problems.
1/ The C# development team, for V1, consisted of 5 individual engineers, a lead, and a couple of PMs. 4 of the engineers worked on implementing the compiler, and the last engineer worked on the Visual Studio integration (e.g., IntelliSense).
2/ The C# compiler was written entirely in C++ as was much of Visual Studio at the time. Everyone on the team wanted to implement the compiler in C#, but as I mentioned previously, expediency was key and when we started, we needed to bootstrap. That was done in C++, so it stuck.
3/ The compiler was largely implemented as a batch compiler. We had a no-release heap, which was extremely efficient for straight-through compilation and totally useless for interactive scenarios. Therefore, the compiler and what we call the language service were implemented
1/ It's probably not the first thing you think of, but when we started .NET (COM+) in the late 90s, C# didn't exist yet. We were working on it at the same time as the CLR and the framework. So, you might wonder, what language was being used to generate IL and write the BCL?
2/ The answer is a language that we called SMC that Peter Kukol wrote the compiler for. Peter is a flat out amazing engineer and wrote the core parts of the compiler in just a few days. This unblocked the framework team, allowed vetting the runtime and interpreter, etc.
3/ SMC was a trimmed down C++ variant and the compiler was written in itself (i.e. SMC). It didn't support things like destructors, multiple inheritance, virtual base classes, etc. But, overall it enabled progress that would have otherwise been stalled.