Essential C#: An Interview with Mark Michaelis
Larry O’Brien: When C# first came out, it seemed a relatively straightforward language to learn and teach, at least to people exposed to another language with C-derived syntax. Is real mastery of C# still a reasonable goal, or is it becoming more like C++, where mastery of every aspect of the language is actually quite rare?
Mark Michaelis: Today, developers can write large effective programs without ever needing to know all the features of C#. However, knowing the full fidelity of the language allows developers to write more succinct and maintainable code in particular areas than they would have if they were unaware of the feature. Knowing all the constructs allows a developer to choose the tool that best suits the task. (Sure, you could use a flat screw driver to pull out a Philips screw but having a Philips screw driver will be far more effective.) Consider the yield keyword: it is fairly seldom most developers need to write an iterator. However, on the rare occasion they do, it is well worth at least knowing the feature exists and what it does so that they can look it up and take advantage of it rather than writing an iterator implementation from scratch.
The only time that I don’t consider it optimal to learn a language feature is when it is superseded by a later language feature – one that came in a later version. For example, there is little point in using the new keyword to instantiate delegates in C# 2.0 or higher. Simply assign the method directly (C# 2.0), use an anonymous method (C# 2.0), or use a lambda expression (C# 3.0). The older syntax still works of course, but is effectively deprecated (In my book I moved such syntax into Advanced Blocks as it is less relevant to the average reader.)
Larry: People use the phrase “dynamic languages” to mean a lot of things. What’s that phrase mean to you and how do you see C# in that sense?
Mark: The key concept I associate with dynamic is “runtime resolved,” meaning that the binding of a request to the target doesn’t happen until runtime. There are many things this enables but th two I appreciate most are:
- Scripting: The idea that I could have a command console that uses any .NET syntax language (including C# of course) against .NET APIs. (PowerShell is an example of this but I am disappointed with the syntax.) The idea of C# on the command line (with the addition of a pipe operator perhaps) is very appealing. Similarly, VBA type add-ins that enable application customization and extensions could be implemented more fully – a feature available in COM that we still haven’t seen from Microsoft with .NET.
- Dynamic Binding: The example I use in my book for this is programming against an XML file. Given a Person XML element, a call to person.Name is so much more appealing than xElement.Descendants(“Name”).FirstOrDefault. Similarly for programming against a database or csv file. The point is that there are situations where a call simply can’t be verified until run time but responsibly waiting until runtime makes for a much better syntax without any negative consequences that weren’t there anyway (such as data not being there).
Larry: How prevalent do you think dynamic type extension should be? Should metaprogramming be a forefront issue for every developer, rarely used, or something in between?
Mark: Like virtually every aspect of C#, dynamic is relevant in some situations and not others. However, when it is relevant, it would be a shame to miss out on its advantages.
Larry: Before the obligatory “What’s new in C# 4?” question — What’s an aspect of C# that’s been in the language for a while that you think is under-appreciated and under-used?
Mark: Of course this depends. I am still amazed but the amount of times generics (a C# 2.0 feature) are not used when they should be and, similarly, how frequently I talk with developers that haven’t yet taken the time to learn LINQ (a C# 3.0 feature). It is hard to conceive of a real world program where both of these language features are not used significantly – what program doesn’t have a collection of something?
Larry: What’s new in C# 4.0 that calls for some in-depth study and where the guidance of a book is really going to pay off?
Mark: In C# 4.0, I am most excited about the new multithreading features that come with System.Threading.Parallel. This is not a language feature per se, but it is a base class library feature that allows me to write loops (such as for and foreach) so that they run in parallel rather than synchronously. These API are very similar to the corresponding synchronous language constructs:
static void EncryptFiles( string directoryPath, string searchPattern) { IEnumerable<string> files = Directory.GetFiles( directoryPath, searchPattern, SearchOption.AllDirectories); Parallel.ForEach(files, (fileName) => { Encrypt(fileName); }); }
This is awesome! I re-wrote both my multithreading chapters in entirety for Essential C# 4.0 in order to cover the full fidelity of the new parallel capabilities.
Larry: Probably the first thing that jumps out about your book is its scope. It’s a big book, just short of 1000 pages, but it's not a reference book per se. Do you expect people to pick up the book at Chapter 1, Page 1 and continue right through to the end?
Mark: If you had asked an "or" question, I would have answered yes. As it is, the answer is yes for both options, but that it not the only type of reader I target. (In fact I hope that it can serve as a reference long after reading it for the first time as well.)
In the original writing of the book, I re-wrote chapters multiple times for the very purpose of trying to effectively target as broad an audience as possible. To ensure that experienced programmers were effectively targeted, I moved concepts that they would generally be familiar with (such as object oriented programming) into Beginner Blocks with the intention that they could easily skip such sections. The blocks serve the dual purpose, therefore, of providing introductory material for the beginning programmer while allowing the experienced developer to easily skip over material they already know. The general text is targeted for those looking to add another language to their quiver. Similarly, there are occasions, like in Chapter 3, where I provide a table that summarizes the syntax when it overlaps considerably with C++ or Java. Again this allows people to easily skip sections where the details of the text are perhaps a little more verbose than the C-derivative language readers would like.
Those already familiar with C# are not ignored either. Firstly, there are Advanced Blocks which go into more detail such as internals of how the compiler implements a particular language feature within IL. Secondly, the appendix includes an index of the enhancements that come with each version of the language. In this way, a C# 2.0 developer, for example, is able to focus on just reading the sections of the book that will help them upgrade to C# 4.0.
Lastly, the material is designed to serve as a reference if a reader wants to quickly lookup a particular syntax.
Larry: An interesting characteristic of your book is that every chapter begins with a mind map. Tell us a little bit what a mind map is, why you chose to use them, and how a reader might use them to guide their reading.
Mark: Mind maps are graphical representation of hierarchical information – a graphical outline. One of the hardest tasks in writing the book was organizing the material to meet the following goals:
- Target developers at all levels of experience
- Avoid a repeat of material
- Move from the general concepts to the language detail
- Transition through the programming paradigms: procedural -> object oriented -> functional ->multithreading->etc.
To achieve this I outlined the chapter using a mind map that enables the reader to familiarize themselves with the chapter structure at a glance.
Larry: One model for a book’s source code is to grow a single demonstration from simple to complex over the course of the book. Your book uses short snippets that stand alone. Why did you choose that approach?
Mark: I have used both approaches for books I have written over the years. When explaining a technology such as ASP.NET, WCF, or WPF, I lean towards using a single example that grows in the number of features and its complexity through the book. However, for language books to remain relevant as reference material long after the initial reading, it needs to be possible for the reader to jump to a page and quickly brush up on a particular syntax, construct or API. By avoiding the clutter of a full example and instead focusing on the feature being described, it is not necessary to read it sequentially and even to skip entire sections that are not relevant at the time.
Larry: One thing that really resonated with me is your emphasis on different programming paradigms: sequential, structured, OOP, functional, etc. Do you see these as something that a developer moves through sequentially over their career (in a waterfall, as it were), or is there an ebb and flow where it’s okay to move back to a mindset you’d previously moved away from?
Mark: For the most part, the different paradigms represent transitions the industry went through as the complexity of applications increased. Similarly, I think we too rely on different paradigms and the complexity of our programs increase. I can write a small maintainable console application using a procedural paradigm. However, as applications become more complex involving many entities, complex UI, or multiple threads, I need to make paradigm shifts to meet the increased complexity. Procedural programming of multiple threads limits its effectiveness. Similarly, complex windows programming without events is unmanageable. Ultimately, we need to pick the programming paradigm in a similar way to choosing tools – pick the right tool for the job. Using a hammer for everything will result in lots of dents and sore thumbs.
Larry: What are the trade-offs of a multi-paradigm language versus a language that embraces a paradigm (e.g., Smalltalk, Haskell)?
Mark: By supporting multiple paradigms, a single language is able to effectively target multiple scenarios. This way a developer doesn’t need to endure a language change when presented with the need for a paradigm shift. The cost of course is a more complex language to learn. However, it would be reasonable only to learn the parts of the language one needs at the time, rather than learning it in entirety.
Larry: When it comes to parallel programming and concurrency, do you feel that C# has a good model, a model that’s sufficient, or a model that will need to change in the future?
Mark: Hmmm.... The parallel APIs are very close to “good enough” so changing the language to support parallel would be a stretch but still possible. In the C# 4.0 round of the language design there is little doubt that there was lots of discussion within the C# design team about whether to include native C# support and so far it was rejected. In the future? ....time will tell. However, there is some attractive support in F# for synchronization because of the prevalence of immutable types. It wouldn’t surprise me if C# adopted some this capability in the future.
Larry: Where else do you feel that C# could continue to evolve?
Mark: I already mentioned two that I find particularly attractive: Firstly, some form of C# scripting (VBA like or a command console) would be great enhancement. Secondly, support for immutable types would reduce the burden of synchronization whey using the System.Threading.Parallel. I can’t say whether either of these is under serious consideration but think in the right form they would be positive additions.