Sponsored Link •
Eric Gunnerson, the C# Compiler Program Manager at Microsoft, talks with Bruce Eckel and Bill Venners about several architectural design decisions in .NET, including multiple inheritance of interface, the emphasis on messaging over mobile code, internal access in assemblies, and the side-by-side execution answer to DLL Hell.
Eric Gunnerson, after having previously worked at a large Seattle aerospace company, a medium-sized PC database company, and a small VMS utility software company, joined Microsoft in the fall of 1994. After several years working on Microsoft's C++ compiler quality assurance team, including three years as the test lead on the Visual C++ compiler, Gunnerson took on a new assignment: testing the compiler of Microsoft's new language, C#. To more effectively perform his quality assurance role, Gunnerson joined the C# design team, where he spent several years working with Anders Hejslberg, Peter Golde, Scott Wiltamuth, Peter Solich, and Todd Proebsting on the design of C#. In 2002, after the initial release of Visual Studio.NET, Gunnerson switched from quality assurance to program management. He is currently the C# Compiler Program Manager. He is author of A Programmer's Introduction to C# (APress, 2001), and writes a column for MSDN, Working with C#.
On July 30, 2003, Bruce Eckel, author of Thinking in C++ and Thinking in Java, and Bill Venners, editor-in-chief of Artima.com, met with Eric Gunnerson at Microsoft in Redmond, Washington. In this interview, Gunnerson discusses several architectural design decisions in .NET, including multiple inheritance of interface, the emphasis on messaging over mobile code, internal access in assemblies, and the side-by-side execution answer to DLL Hell. Comments are also contributed by Dan Fernandez, Microsoft's Product Manager for C#.
Bill Venners: The CLS, the Common Language Specification, has single inheritance of implementation, multiple inheritance of interface. Could you explain what the CLS is, and how the inheritance model was was decided upon?
Eric Gunnerson: The CLS describes how languages should behave so they can play nicely together. For example, C# has unsigned types, but unsigned types are not in the CLS because languages like VB [Visual Basic] can't handle them. I think of the CLS as an interoperability spec. If you adhere to the CLS, then you can interoperate with the other languages.
Multiple inheritance has two or three big issues. First, trying to get people to agree what multiple inheritance actually means is difficult. If we try to do multiple inheritance in the CLS, we would probably choose something along the lines of multiple inheritance in C++, and that would put languages that have other kinds of multiple inheritance in an ugly state. People would say, "Microsoft supports multiple inheritance, but they support it wrong. I can't make my language work using what they have." People would make that argument.
A second issue for me is just the cognitive complexity involved—what it takes to understand what is really going on in your code when you start using multiple inheritance. I think multiple inheritance is kind of like the advanced operator overloading in that respect. To really understand what's going on you have to think deeply. It may not hit you in a lot of cases, but there may be cases where something works strangely and you have to dig deeply to understand it. You should tend away from that kind of complexity when you are doing object design.
Now obviously one other question is, given that we're multi-language, what would you do with languages that don't support multiple inheritance? I don't see how we could ever put multiple inheritance in the CLS.
Bruce Eckel: What do you do with managed C++? Does it have multiple inheritance?
Eric Gunnerson: They don't allow multiple inheritance in managed C++ classes.
Bruce Eckel: I see, if I want a VB program to use this C++ class, I don't use multiple inheritance.
Eric Gunnerson: Another problem with supporting multiple inheritance is that if you were designing with multiple inheritance, you would do class libraries differently than you would with our current system. But then you can't do that, because some languages don't support multiple inheritance. So you might bifurcate the libraries—have one way for the multiple inheritance languages and one way for the other languages. But that would make the libraries very hard to understand.
Bruce Eckel: Does the CLS allow multiple interface inheritance?
Eric Gunnerson: Yes.
Bruce Eckel: But that's a reasonable constraint.
Eric Gunnerson: It's a reasonable constraint if nobody causes you to do anything that makes you burn your base class.
Bill Venners: Burn my base class?
Eric Gunnerson: I'll give you the canonical example. When you want to make a
component a remote object, you must derive its class from a base class called
MarshalByRef subclasses get marshaled,
they get marshaled by reference. You get an object over here and a proxy over there, and the
runtime handles all the mechanics. That works great, unless you actually want to use
inheritance in your design. Because the designers of remoting decided to do this with the base
class, they took the option of using inheritance in any other way away from you. They
burned the base class.
Bill Venners: They burned the base class because if I want to remote something, I have to extend their class, not some other class I may want to extend.
Eric Gunnerson: Maybe you can get away with extending a class of yours that extends their class.
Bill Venners: But if it doesn't already extend their class and I can't change it, then I'm out of luck.
Eric Gunnerson: Yes, exactly. The constraint in supporting single inheritance of implementation, multiple inheritance of interface is that you have to pay a lot of attention about what you do. In fact if you go talk to customers that use remoting they say that exact same thing, why are you burning a base class here? You don't need to. You could use attributes or some other mechanism.
Bill Venners: So in design you should be careful not to burn your base class.
Eric Gunnerson: Yes. In design you have to be very careful.
Now, just because the CLS only directly supports multiple inheritance of interface doesn't mean that individual languages can't support more. Eiffel on .NET has multiple inheritance, for example. When compiled, it uses multiple interface inheritance and creates classes under the covers as necessary. So they do support full multiple inheritance, because Eiffel without multiple inheritance is way worse than C++ without multiple inheritance. A lot of common Eiffel idioms require multiple inheritance. It's just the way you write Eiffel code.