Anders Hejlsberg joined Microsoft in 1996, and did his initial work as an architect of Visual J++ and the Windows Foundation Classes (WFC). Hejlsberg is currently a Microsoft Distinguished Engineer and chief architect of the C# language, and he played a key role in the creation of the Microsoft .NET framework. Today, he leads the ongoing development of the C# programming language. John Osborn, executive editor with O'Reilly Media, Inc., responsible for the company's developer books on .NET and other Microsoft initiatives, recently sat down with Hejlsberg for this second part of a two-part wide-ranging interview.
Osborn: [When you introduced the C# language in 2000], your number one bullet was that this was the first language that was really component-oriented. Has [your] perspective changed in five years?
Hejlsberg: Well, it's become more than that, for sure. But [C#] is still what you could characterize as a component-oriented language. And that takes us back to properties, methods, events, and the core things that you deal with on a day-to-day basis in your programming. Back then, and even more so now, programming very much is aided by tools, and those tools very much tend to have a programming model where you have some sort of design surface where you put components, and then you modify the components, put code behind them, set their properties.
I always felt that [properties and events and methods are] such important concepts that they deserve first-class treatment in the language, and that's what we did with C#. And quite honestly, I have heard no complaints about the fact that we have properties. It is a complete non-issue, you know what I mean? It's just, "Yep, yep," people just think that's completely natural.
And in a sense, this idea of giving first-class treatment to things that we commonly do is something that is very dear to my heart. In many ways, it's the same [thing] we're doing with LINQ and language-integrated query, right? It's giving first-class treatment to the notion of a query in a programming language, because we all like queries. It's a declarative way of expressing something at a higher level than if you write a bunch of
for loops and
if statements and sort of do it the manual way.
Osborn: I want to come back to LINQ, but going back to the relative positioning of languages, again, one of the things that [Microsoft Visual Studio .NET product manager] Tony Goodhew said in that interview was that Microsoft studies were showing that people tended to use two or more languages to do their programming. And there was a sense at the time that [languages were just] syntactic sugar. You choose the language that you're most comfortable with.
Do you think that's changed? We don't say that anymore.
Hejlsberg: Well, we don't, but it's all syntax in the end, right? I mean otherwise, we'd just be handing over an XML document that describes the abstract syntax tree of what you want done, and that could be the syntax, too, but it's obviously not usable by programmers. So I think programming languages occupy a special position in people's minds in the sense that just as your spoken language is the way you express yourself, so is [your] programming language; it's how you express yourself.
And the syntax is the manifestation of the programming language, and it actually, in many ways affects how you think about your program and so forth. So syntax does matter, and it matters a lot, I think.
Osborn: What's special about C# in that regard? Can you characterize it?
Hejlsberg: Well, I think the component-oriented stuff that we talked about is tremendously important. We try to make sure that there are not multiple ways of doing things. We try to always find synergies between syntactic elements. It's hard to describe precisely what I mean by this. But take the language-integrated query [LINQ] stuff [we've introduced at the PDC, for example]. The extensibility model of that is that we turn it all into method calls. When you write a query with a
orderby, and a
select clause, we turn that into calls to methods called
Select on the collection you are querying. And we pass the expressions you wrote in the query as lambda expression arguments to those methods.
So queries just turn into method calls that are strung together, but the query syntax makes it easier to read, even though it is simply a syntactic veneer. It immediately translates into method calls, just like the
foreach loop translates into get a numerator on a
while loop and so forth. But it helps you think about it at a higher level. Do you know what I'm saying?
Hejlsberg: So in that sense, syntax deeply affects how you think about the problem, even though semantically it has absolutely no bearing on what's going on.
Osborn: Yes--from the perspective of a book publisher, and [by looking at] our own tracking data, we see that C++, oddly enough is holding its own; it's actually grown a little bit in terms of book sales, whereas VB has declined probably 20 to 25 percent in the last year. C# has been very steady [Ed.: But flat].
Osborn: So clearly, from what we're seeing, there seems to be a migration from VB to C# [Ed.: Or perhaps elsewhere]. But C++ seems to have its niche.
Hejlsberg: Right. VB and C# very much appeal to the same crowd of programmers. C++ does play in the managed space, but C++ at [its] core is really about writing unmanaged code, and a lower level of programming. I know I'm generalizing here, and yes, you can [do] template-based [programming] and [use] STL [Ed.: The standard template library], and I'm not meaning to belittle anything. I'm just saying it's sort of broad position and the broad clientele of C++ tends to write a different type of application than you write with [C# and VB].
Where C# and VB very much appeal to the same segment.
Hejlsberg: So I'm not actually surprised that C++ is--
Osborn: You wouldn't choose C++ to write managed code.
Hejlsberg: Personally, no. I would not choose it to write managed code. But if I had to go write a compiler that wasn't going to be managed code or whatever [, I would]. But I think as a general rule, every year that passes, I think the reasons for writing managed code are stronger and stronger. Simply because the hardware is more capable at this point, and the tradeoff, arguably not very large, but the tradeoff that we make for "Let's sacrifice a bit of CPU power and a bit of memory for dramatically increased productivity," is a great deal. I think it is a very worthwhile value proposition. And I think that's only getting more true. Plus the world of managed code is getting richer every day. It clearly is where all the innovation is happening, and where the vast bulk of enterprise apps are being written today.
Osborn: Maybe we should talk a little bit about version 2.0. Certainly, [C# programmers have been] looking forward to generics for a long time.
Osborn: What's different about the generics in C# as opposed to other languages?
Hejlsberg: I think that begs the question of what's different between C# and Java, obviously.
Hejlsberg: First of all, I'm very pleased that we got generics into 2.0. Generics in many ways is the deep enabler of all the stuff that you're now seeing us do in C# 3.0. It is really profound how generics adds a new dimension of richness to the type system that opens up all sorts of possibilities, like language-integrated query, which we could've never done without generics. So in that sense, it's a deep enabler for interesting stuff. It also is a very pragmatic real-world problem solver.
Hey, more typing is good, because that means you find more errors sooner, and you can do better code generation because you have to have fewer dynamic checks at runtime to verify the solidity of the types in your program.
Now, with respect to Java and C#, syntactically, the two implementations of generics look very similar. They [both] look kind of like C++ templates; you can see the heritage there.
But once you scratch the surface, underneath they're actually very, very different. I think the biggest difference is that in .NET, generics are not just a language feature. They are deeply understood by the CLR [Ed.: Common language runtime] and by the type system of .NET itself. So [generics] have representation at runtime.
Java chose a different strategy for implementing generics, where in a nutshell, they're only a compile-time feature. And the [Java] compiler removes all of the genericity from the code, and just emits objects; it effectively substitutes
object for every type parameter. With Java, at runtime, there are no generics. This is interesting in the sense that it allows you to run on an unmodified VM [Ed.: Virtual machine], but it also brings about a host of very surprising limitations and rules that you have to abide by. And it does not give you some of the performance gains that we see from [our own implementation of] generics, because [with Java] at runtime, there are no generics and you have to still do all of the dynamic runtime checks and downcasts and whatever while you take things out of a
But I think the subtler point here is that because there is no runtime representation of generics [in Java], you lose some information going from your compiled code to the code that you run at runtime. So at compile time, you might be operating on a list of customers. If at runtime, someone hands you a list of customers typed as
object, they just give it to you as an
object, and [if ] you want to find out what this list is a list of, you can't, because reflection doesn't know about generics because that got erased.
And so you have these strange holes in the system, and in a world where we rely increasingly on dynamic code generation and inspection--of running code and dynamic behaviors and whatever--that is actually, to me, probably the biggest issue that I have with Java's implementation of generics; that is, this lack of true representation of the program being run.
Osborn: So you're saying that the [.NET implementation of] generics allows you to hang on to the--
Hejlsberg Oh, certainly. If I give you a
List<T> typed as
object, I can ask it, "What are you?" and it will say, "I am a list of customers." It'll say, "I'm a
Customer." Then I can say, "Well, why don't you give me just the
List<T>? And in fact, why don't you bind
Order?" And now I can make myself a
List<Order>, and then I can create instances on that. Anything I can do at compile time, I can do at runtime too, through reflection, and that's tremendously powerful.
Osborn: What about the addition of anonymous methods? I remember when that [feature] was announced, and I was talking to authors, saying you have to add anonymous methods to [your] text, but not really understanding why I was asking them to do that. I'm sure there are use cases for anonymous methods that [people reading this want will want to know about. But also, it's interesting to see how anonymous methods, like generics, are an enabler for new features in C# 3.0].
Hejlsberg: Oh, absolutely. And, you know, honestly, first of all, let's give credit where credit is due. I am not inventing anything completely new here. It's all based on this thing called lambda expressions or lambda calculus or whatever, which has existed in the functional programming space for decades. But somehow, that has never really seen the light of day in a mainstream programming language.
And C# is fortunate enough to be among the first to do that. We're very serious about evolving that, and that's what you're seeing in C# 3.0, where we evolved anonymous methods even further into these things we call lambda expressions now, where we have surrounded them with rich type inference, for instance, so you don't have to say a lot of the stuff that you would have to say manually before.
Hejlsberg: In terms of why they're important, let me illustrate it by an example. In C# 3.0 we're introducing this notion of language-integrated query [Ed.: LINQ]. And really, what we're doing is we're making it possible to build a query language as an API. You know, out of methods called
GroupBy and whatever. You can see that if a collection has a
Where and a
Select and an
OrderBy, and a
GroupBy method, then you can sort of string them together, and you can build a whole query language out of [them].
But if you were to do that in a language that doesn't support anonymous methods or lambda expressions, then if you think about how you would implement a
Where method, well, it wants to take a predicate as an argument, right? A
test to apply to each element, you know what I'm saying? So I want to say
list.Where(blah), and the
blah I want to pass in is a test.
But it's not like a parameter in the normal sense, because I'm not passing in just a
bool argument, because that obviously would [require that the test] get evaluated up front and then passed in. And I don't want to see
false, I want to be passed the test itself. You know what I'm saying?
Osborn: Yes, you want to pass a procedure to be executed?
Hejlsberg: Yes. And really, what I want is, I want a reference to some code that I can execute, right? I want a function reference or a method reference passed to the
Where operator, such that the
Where operator can run this code for each element that it's trying to test, and then, you know, return me all the elements for which this test is true. And if you look at how the
Select operator (i.e.,
projection) works, it's the same. It's like, give me an element, and give me a function that can make an element from one thing to another. That's a projection.
OrderBy, it's like, give me something that can compare two elements. Again, it's a piece of code. So really, the thing expressively that has been missing in programming languages is the ability to pass code as parameters.
Osborn: That's the significance--
Hejlsberg: And that, is in a nutshell, what lambda expressions and anonymous methods allow you to do. And by the way, lambda expressions and anonymous methods are really just two words for the same thing. The only thing that differs is, "What does the syntax look like?" And the lambda expressions are a further evolution of the syntax. But underneath, they do the same thing. They generate methods. You know, they're in-line methods.
Osborn: What else besides generics and anonymous methods should people be paying attention to in 2.0?
Hejlsberg: Nullable types, I would say, is a pretty important advance, too. Because it's one of the steps on the way to bringing parity between the database world and the general-purpose programming world. You know, it's very hard to talk about meaningful mappings between the two worlds when one world, the database world, is entirely based on nullable types, and the other world doesn't have them at all.
Hejlsberg: And of course, you can fake your way out of it--
Osborn: Which you have to do--
Hejlsberg: --in the general programming world, which, you know, people often do by boxing, for example, or by allocating an object in which they store the value, and then using
null if not. And that's effectively how Java does it. But it ends up being very expensive to do it that way. Because in order to represent an integer value that can possibly be null, typically the way it's done in Java is that you use the
Integer wrapping class, and you allocate instances for each
int value, and then you just use
null as the null.
Hejlsberg: But you quadruple the memory consumption for each
int, and you incur an indirection. So there's a lot of cost associated with that, where with nullable types in C#, we effectively give you the ability to make value types null, but we don't do it by allocating objects in the heap. We do it through a generic type that couples a
T and a
bool. It's called
Nullable<t>, and it has two fields inside of it, a
T and a
Nullable<T> is itself a value type. So it actually gets stack allocated or in-line allocated and it's much more efficient from a memory standpoint than other solutions that are out there. And over and above that, we have language syntax to support nullability. We have this question mark (
?) type modifier.
int is an integer,
int? is a
nullable integer, and there are implicit conversions from
int to nullable
int, and explicit conversion the other way that will throw a null exception if the thing is--like all the things that you would naturally expect of a language that deeply supports nullable types as a proper concept. So again, it's this thing about giving first-class treatment to a thing that people use every day.
And again, for me, as a language designer I look at, "What are people doing out there? And what is it that we need to think about giving first class treatment to?"
Osborn: So is C# one language to rule them all?
Hejlsberg: [Laughs] No, no. I think not, I don't really think it is. There are lots of things for which other languages are more suited. C#, at its core, is a strongly typed language. And for certain things, you know, dynamically typed languages are more appropriate if you're just going to write a few lines of code, and you don't want to first have to do a bunch of declaring upfront. You just want to sort of try it out.
But within the family of languages that it's in, sure, I aim to take it as far as I can.
Osborn: In relation to 2.0, are the changes that we're seeing in the Microsoft implementation also being proposed as standards?
Hejlsberg: In 2.0?
Osborn: In 2.0.
Hejlsberg: Yes. The standard will be called "third edition," but it's actually the one that we're calling 2.0.
Osborn: So there's no aspect to it that's Microsoft only in terms of the changes.
Hejlsberg: No, every language feature in C# 2.0 has been submitted to ECMA and is in the standardization process. And we expect fairly shortly for the community to vote, and it's really a matter of procedure at this point. (Ed.: This has already happened. See www.ecma-international.org/news/PressReleases/PR_TC39_CSharp_CLI.htm.)
Osborn: So probably by the end of the year?
Osborn: As far as 3.0 goes, I've been [reading] what [bloggers and columnists] have been writing about [about the new LINQ extensions] and it seems that everyone's getting the message about why it's significant. I'm just wondering if we're missing anything that you wish people were paying more attention to in reacting to those changes.
Hejlsberg: No, I think people by and large get it, because you have to see but one example, and then you go, "Oh yeah, I need this." The notion that we can have a single unified way of querying objects, relational data and XML is in many ways a holy grail that we'd all like to get to. And I think we've made significant inroads towards that with the language extensions that we're doing and the LINQ project.
Osborn: It took me two presentations to get it, but I realized that there's a set of innovations in C# that are interesting to look at in their own right, and [that the LINQ project] is really a layer on top of it. [We touched on that earlier, but] could you talk a little bit more about [the C# 3.0 language extensions that make LINQ possible]?
Hejlsberg: Yes, I think you do hit a good point there that is quite subtle. There are many ways we could've gone about this. And you can speculate about, let's say that we all agree, gosh, it would be great to have query inside your programming language. We're not the first to have this idea. So what is it that's different about our approach from those that have gone before?
If you compare it to, for example, embedded SQL or SQL/J or whatever, those extensions also give you the ability to put a query inside the programming language. But really what that approach is doing is just hosting one language within another. [SQL/J] is just hosting SQL in the middle of Java; embedded SQL is just hosting SQL in the middle of C, you know what I mean? With some escapes, that take you from one world to the other, and some fairly crude binding mechanisms that go between the two worlds.
So [neither approach] really gives first-class treatment to the query language. It just puts one language within another. To me, a better approach is to identify and understand what it is--expressively--that is missing from, say C#, in order for it to be rich enough that it could itself be the query language. And then isolate those features and add them to the language. But also, add them to the language in a way that does not bind us to a particular technology.
I mean, I think, and as I said in my talk yesterday, [that would be the case] if we were to say that C# only works with SQL Server 2000 or whatever, for queries. That'd be the death of C#. Not to imply that there's anything wrong with SQL 2000, of course, but as a programming language, you have to be one step removed from that. You need to always think about the class of problem, not the particular instance of the problem, right? Customers always come to you and say here's the instance I want [solved]. And I always try to think about, "Well, what is the class they're talking about?" You know what I'm saying? Effectively, the big difference in approach with C# 3.0 and the LINQ project is that there is complete separation between the features that we added to the language, and the particular instances of use of those features like DLinq [for relational databases] and XLinq [for XML documents] and the standard query operators [for objects in memory].
And anyone could go write a different set of APIs if they feel that we didn't quite do it the best way, and all of the features in C# 3.0 are still relevant. So they stand on their own merit. But the synergy of the two, of course, is what drives the whole thing.
Osborn: I was hearing, in the C# presentation, a lot of "oohs" and "ahs" about extension methods, and some of the other innovations that you were going through. And [the extensions getting the accolades] didn't have anything to do with data per se.
Hejlsberg: Right. There are deep reasons for what we're doing, but they have other good uses. Take lambda expressions, for example. The ability to create expression trees out of lambda expressions got lots of interesting uses in event notification systems where you want to give a trigger, which is really a predicate that you want to give to the system in some form, that the system can reason about it and so forth.
Rules engines, constraint systems, there are all these other things that you can do with this stuff; we're just looking at the tip of the iceberg here. I think there's a whole bunch of stuff. In many ways, that's why so many people are interested in functional programming languages and why academia has so much energy going into that; there is a whole class of problems that all of a sudden become relevant once you have these capabilities in the programming language.
Osborn: One of the things you seemed to be saying in the presentations was that the approach that's built into C# has a lot of advantages over just plain SQL type queries in terms of memory use and that sort of thing. Is that worth talking about?
Hejlsberg: Well, I think I was saying a couple of things there. First of all, SQL obviously only works for relational data, where the stuff we're doing here is much broader. It's a query language that works on objects, and those objects can represent relational data, or they can represent just in memory instances of a class, or they can represent XML.
So in that sense, it's broader. In terms of the memory efficiencies of it, I think at that point I was talking about the XLinq API. You can think of XLinq as doing two things. It brings language-integrated query to XML, and it takes advantage of the ten years of experience that we have with the XML DOM, which is the foremost XML API that people use today in their applications.
And there are a bunch of design decisions that were made in the XML DOM that at the time seemed relevant, and then over time we realized that these are not important things to have. But unfortunately, because we have to have this particular feature, memory consumption doubles. It's like, you know, the ability to store unparsed entities in attributes; I know that this sounds like complete geek speak in XML terms, but it's like this completely esoteric feature that you need .001 percent of the time.
Yet the fact that you have to be able to represent it deeply affects how you internally structure your attribute storage. You can't just store an attribute as a string, because it now has to be a list of content elements and so forth, and stuff like that adds a bunch of overhead that we all pay for every day even though we never use it.
So we made some judicious choices about, you know, now that we have all this relevant information about how people use XML to deeply shape the data structures that underlie the XLinq API. And we get some big benefits from that. I was saying between 30 and 50 percent savings in memory consumption. And typically, you can equate that to better performance, too, because hey, you use less memory, you're going to perform better as a rule of thumb.
Osborn: The basic syntax for all three types of queries is really the same in C#. How should we think about the separate pieces that we need to download? DLinq, XLinq and the Standard Query Operators. Are they all just part of the same package? Why are you making that distinction in the way you're presenting it?
Hejlsberg: It's a question of classes versus instances. There's the class of problem we're solving, which is the ability to query objects, or object wrappers, really, in a sense, because they don't necessarily have to be existing instances of objects. That class of problem is what language integrated query is about. It's the notion that, given a class declaration, given an instance of some class, you can write a query against it where you refer to its properties and the properties of that, and whatever.
And you're not necessarily actually holding real instances of real objects at that point, because objects can be proxies for things. That's how O-R [object relational] mappings work, right? And that's what gives you the ability to write what appears to be a query against all of the orders in my database, when none of them have been materialized yet. So because objects are very powerful in that way, you can actually expressively do a bunch of stuff.
But then underneath, we can implement it through an O-R mapping. So what you're seeing, really, there's the class of problem we're solving, and then you're seeing specific instances of that class of problem. One is this API we call the Standard Query Operators, which just says here is a relationally complete, hierarchical query language for anything that implements
And by the way,
every array or collection in .NET does. And that's sort of the super low barrier to entry to this system. It's the instant gratification effect. Bam, you can query any collection you have, any array you have in memory, and so forth. But then we also say well, that's great, but now there's relational data, right? Well, relational data, we could sort of do the dumb thing and just suck the whole table into memory and then use the standard query operators to query it, but that's obviously not acceptable.
So here we have another instance of the problem we want to solve where we actually want different execution semantics. Instead of executing the query in memory, we want to capture an expression tree, and remote that [expression tree] to the database in SQL form. So effectively, [we want to] capture an expression tree, translate it to SQL, send that to the database, and then create objects as the results come back. And illusion is that "Hey, the query looks exactly the same," but boy, the way it executes is totally different.
And then for XML, well, that's a different world again because now you're talking about a different type of data structure. You have an XML object model, which has looser typing than CLR objects, and different semantics and so forth. But the base query language still applies.
So that's how you should think of them. They're just different instances of the same class of problem. But the subtle difference is that, well, now APIs can be query-enabled, just like they can be persistence-enabled, or remoting-enabled. Querying becomes a new
capability in an API.
Osborn: So what you're getting with the different packages is different sets of APIs for carrying out those--
Hejlsberg: They're different APIs that are query-enabled, yes. So that's an attribute of the APIs, if you will.
Osborn: Gotcha. A couple people have quoted you as saying you think you've solved 90 percent of the problems out there. What's the other 10 percent?
Hejlsberg: [laughs] You mean like in computing in general?
Osborn: In relation to query. [The implication, I think, is that] there is still a need for some specialized query languages [whose functionality] we couldn't approach yet through what's in C#.
Hejlsberg: Well, I think we're certainly trying to cast a very wide net here, and capture as much as we possibly can. But I don't expect this to be the be-all, end-all of query as a concept. Well, obviously SQL's going to be around for a good, long time. And I'm not naïve in thinking that we're going to get rid of SQL or get rid of XQuery or whatever. No, no, no. We're going to be complementary to those technologies.
We're going to be a great tool that you're going to have available if you're coding on the .NET framework. But this brings to mind another design principle I have whenever I'm involved in designing APIs.
For example, with DLinq it's great to be able to write language-integrated query because it's going to get you there quicker, faster, you're going to be more productive, and so forth. But sometimes you're going to want to write some esoteric SQL query that uses some user-defined function, calls some stored procedure, or whatever. You know, there's always some reason why occasionally you have to do that. And part of the DLinq API is what you could think of as the SQL escape hatch. So you can write a language-integrated query, but we also have a method in there called
ExecuteQuery that takes a string that is a SQL query.
And then you get to say the type of the result using a type parameter. So you can say
ExecuteQuery<Customer>("select * from customers where ...") and call some user-defined function in the SQL query. And then we will treat the result of that as instances of type
Customer. So you still get all of the other DLinq features, such as referential identity, change tracking, and the ability to submit changes back to the server, and so forth.
I was also involved, earlier in my career at Microsoft in designing the Windows forms APIs. And in there, for example, there's also an escape hatch that allows you to get the underlying window handle, and just call User32.dll functions directly, because sometimes you just need to. There always has to be an escape hatch that gets you back to the underlying technology.
You know, all too often, encapsulations think that their purpose in life is to hide. That is not their purpose. Their purpose is to make something easier to use, but not to hide what's underneath.
Osborn: Now that you have achieved all of this here, what's next? What's the new frontier?
Hejlsberg: Well, let's see, next is, ship C# 2.0, and then ship 3.0.[laughs]
Osborn: Yeah, I should ask you about the timeframe. You are releasing a CTP--
Osborn:--at the show [PDC 2005] for people to play with.
Hejlsberg: Yes, and on the Web too. So it's not just for show attendees. Anybody can download it and put it on top of Beta 2. So if you installed the Whidbey beta of Visual Studio 2005, Beta 2, then you can download the LINQ project tech preview and install that right on top. It's just a little six-megabyte download. It has lots of documentation in it: an overview of the LINQ project, the C# 3.0 language specification, the standard query operator spec, DLinq, XLinq, and lots of examples, so people can really just install it and sit down and completely understand--
Osborn: Yeah, I was impressed with the 101 examples your team has posted.
Hejlsberg: Yeah, I'm so happy we have that little app, because it is so darn useful for people. Because programmers want to see code, and they want to see the results of writing the code. And that is exactly what that thing does.
Osborn: Sure. So there will be a beta; the beta's scheduled pretty much in line with the Orcas schedule, do you think? [Ed.: Orcas is the next major release of Visual Studio, expected sometime in the first half of 2007.]
Hejlsberg: Well, we're targeting the Orcas wave of products with this technology, yes. That's about as specific as I can be at this point. Once we have the final RTM version of Visual Studio 2005, we will refresh the technical preview of the LINQ project to sync with that, so you can use LINQ, the preview, on top of the shipping product. So that much, we know that we're going to do.
But I can't tell you when the Orcas wave of products exactly is going to be, and so forth. And I can't give a you 100 percent guarantee either that [all of the announced C# 3.0 and LINQ extensions] are going to be in there, but that is certainly what we're aiming for.
Osborn: To summarize, what would you like people to remember about--what should programmers be doing with 2.0 and 3.0 right now?
Hejlsberg: With 2.0, I would urge them to take advantage of generics and the stronger typing that you get in your programs. It's such a win-win situation. It's like having your cake and eating it too. So I would urge people to take advantage of that in their apps. With 3.0, I think it's important to take a look at the technology preview that we're giving out here, because this really gives a glimpse into the future of what's happening.
And also, I would love to get feedback on this technology. We're really, I would argue, doing some deep innovation here in the language. And that means we're treading new ground, and we need feedback more than ever on whether we're going in the right direction.
Osborn: What's the best way to do that, for people who want to get involved?
Hejlsberg: When you install the LINQ preview, there are links in there to our forums on MSDN. Many of our team members have blogs that--there are lots of opportunities for feedback that way. We also have our ladybug bug-tracking system where you can actually enter bugs on products and so forth. So, there are lots of opportunities to give feedback.
Hejlsberg: Or email, for that matter.
Osborn: Thank you very much. I hope we can talk again in five years. [laughter]
John Osborn is a senior editor with O'Reilly Media, Inc., responsible for Windows and .NET developer books, PDFs and other content.
Return to the ONDotnet.com.
Copyright © 2009 O'Reilly Media, Inc.