I'm working on resolving an issue, and the way that we decide depends upon the prevalence
of a specific scenario. I'd like to know your opinion on the following Windows Forms
How often do you rename the form class without renaming the file that holds the form
class? ie how often do you change "class EmployeeForm" to "class AddressForm" without
also renaming the form file?
I have a design question for you. Yes, I don't own the project system anymore, but
I started this particular issue, and I want to follow up on it:
In VS 2002, whenever you double-click on a form file in solution explorer, the project
system always opens the form designer on that file.
We are considering modifying the behavior in Whidbey so that the project system will
track the most-recently-viewed state for the file. If you had most recently looked
at the code view, double-clicking would take you to the code view. If you had most
recently looked at the design view, double-clicking would take you to the design view.
This state would not be persisted across closing and reopening the project.
What do you think? Should we stick with the current behavior, or should we change
to the new behavior? And why?
I've been cleaning my office today, and I need some help on a problem I have.
Back when I wrote my C# book (A Programmer's Introduction to C# (still available at
better booksellers everywhere (Eric needs to pay for his season's pass at Stevens
Pass (where it snowed this week (view the webcam))))),
I was lucky enough to have the first edition translated into a number of different
languages. Whenever a publisher would finish a translation, my publisher (Apress,
new owner of most of the Wrox titles) would send me a box of books. I always put one
on the bookshelf, and when I had one that I thought somebody would be interested in,
I'd give it to them. For example, I gave my Czech mother-in-law a copy of Začínáme
programovat v C# , and Anders got a copy of
But after a while, I exhausted the humorous potential of giving relatives copies of
books that not only covered topics they didn't understand, but were written in languages
they didn't speak, and I'm left with a number of copies that I don't know what to
do with. Most are the first edition of the book, which is nowhere near as good as
the second edition.
So I'm looking for ideas of what to do. I currently have:
2 Korean (2nd edition)
I've been diving into generics a bit more deeply, and I'd like to share some of the
new terminology that will be floating around.
An open type is a generic type that you've defined. List<T> is a good example.
It's called "open" because it's not fully defined without knowing what T is, and therefore
you can never have an instance of this type.
The type placeholder that you use when writing a generic type. In List<T>,
T is the type parameter.
A constructed type is what you get when you specify a type for a type parameter. List<int>
is a constructed type, and you can create instances of it.
The actual type you use instead of the type parameter when creating a construct type .
In List<int>, int is the type argument.
A method that has a type parameter on it.
static int Process<T>(T t);
is an example
Strictly speaking, the number of parameters to a method. In generic terms, it's the
number of type parameters on a generic type or method. ArrayList has an arity of zero,
while List<T> has an arity of one.
In VS2003, since we don't have generics, we have lots of strongly-typed collections.
For example, there's the LinkCollection class, which holds objects of type Link.
Now that we have generics, we could replace such collections with:
(well, actually, we couldn't replace them, as that would break existing code, but
we could do that for new collections). That seems like a simple solution, but it isn't
optimal, for a couple of reasons:
The better solution is to define your own collection class. Nicely, you can base it
off of the collection class:
class EmployeeIDCollection: List<int>
The design guideline is not to expose collection classes, but rather to expose custom
collection classes (I really need a better name for those) instead.
I needed a splash screen for my music player app. I tried a couple of ideas that didn't
work very well, but then I hit on the idea of using the image
of a CD as the background of the splash screen - and doing a non-rectangular window.
I'll start with the splash screen...
Conceptually, a splash screen is pretty simple - it's just a form that you bring up
at the start of the program. The code is something like this:
splashForm = new SplashForm();
and we'll hook the Activated event to hide the form.
When we run this, however, something strange happens. The form comes up, but it never
renders - there's just a black background. This is because we need the windows messages
to be processed to get the form to paint. There are several ways to do this, but my
choice is to simply call Application.DoEvents() after the form is shown. This processes
any messages that have yet to be processed, showing the form.
Next, we need to make a non-rectangular form. This is done by setting the region on
the form. This is surprisingly easy to do. Here's the code I used for the CD:
GraphicsPath p = new GraphicsPath();
p.AddEllipse(2, 4, 340, 341);
p.AddEllipse(150, 153, 43, 43);
this.Region = new Region(p);
The first ellipse defines the outside of the picture, and then the second one this
inside. This gives me a round window with a hole in the center.
Thanks for all your comments. On the basis of those comments, we've decided not to
change the current behavior. There are two things I'd like to bring out.
First, thanks to Jacob for mentioning that you can set the default behavior. One of
the problems we have with VS is that there is lots of functionality that people don't
know about. I've added this to my "Things that people don't know about list". So,
if you want to change the default, right click and choose "open with". This works
for both Windows forms and ASP projects.
The second concerns options. There were several comments that say, "make it an option,
so people can choose", and then Monte Hansen said, "I think there needs to be a gatekeeper
for project-level options and if it were me, this one wouldn't make it".
I agree with that sentiment. In some cases, you have to provide flexibility - for
example, if you had a feature that said "braces must go on the line after the if statement",
you would make lots of people unhappy. That would be a Bad
But there are other cases where adding an option is is the simple way out - either
because a team can't agree on what should or shouldn't be there, or because the team
hasn't worked hard enough on what the customer wants (these may really be the same
thing - not knowing your customers well enough). It's easy to say "let's make it an
option", but in a product like Visual Studio, there are already too many opaque options.
There may be some interesting ways of fixing this - like making the options that pertain
to a window actually be accessible from that window - but in the category of options,
fewer is already better.
I was looking through the options in VS2003 for one where I could say, "Does anybody
ever set this option". I had just read Mark's comment:
One feature that disappeared between 2002 and 2003 that really drives me nuts,
was that when you changed between document tabs the project tree view would update
to select the current page you are viewing
and what do I find? Under "Projects and Solutions", there's an option named "Track
active item in solution explorer" that I think does what Mark wants. We didn't take
the feature away, but we did do a good enough job of hiding it that it appeared that
it was missing. That's a good indication of why "make it an option" can be a bad choice
- we put effort both into coding something, making it an option, and then testing
it, but we hide it so that our users get little benefit from it. Many times the effort
to do this just isn't worth the return, as an unfound option is no different than
a feature that doesn't exist.
We had a similar situation back when I was on the C++ compiler team. User asked
us for more information to help them find problems in their code, and there were a
number of situations that the compiler could identify. Unfortunately, in many cases,
the compiler would warn on perfectly reasonable code, and since many people compile
with "warn as error" on, we couldn't make them level 2 warnings, as it would break
lots of existing code.
So we made them level 4 warnings, but the result was that since the default was level
2, almost nobody got any benefit out of the work that we did, so we stopped adding
Thanks again for your comments
You drive into work in the morning, and as you drive around the garage, you see some
green objects blocking a stall at the other end of a row of cars. Your first thought
is, "Cool! Health!"
(They were egg crates, but the color match was pretty close)
(The opinions expressed herein reflect my opinion about the principles we used in
designing C#, and do not necessarily reflect the opinions of the C# design team).
Know what you're trying to build
Over the past few years, I've answered a lot of questions about language design rationale.
Most questions have straightforward answers. For example, if somebody asks "Why doesn't
C# have macros?", that's easy to answer.
Other questions require a bit more work, and/or may be religious discussions. "Why
are methods non-virtual by default?" takes more time to answer.
The toughest ones to answer aren't tough because they're technically hard - they're
tough because it's hard to give a nice answer to. This is usually because doing what
the person requests would require changing one of the basic tenets of the language.
Our goal in C# was to create a modern, real-world managed language that would be comfortable
to developers used to the C family of languages (C, C++, Java, etc.). So, when I get
questions like, "Why is C# case-sensitive?", they're really hard to answer. The real
answer is that our target users would think we were crazy if we made a language that
wasn't case-sensitive. You can say this in a polite way, but the person who asked
the question is usually confused by your response. Their perspective is often "of
course a language should be case-insensitive", which is diametricly opposed to the
Similarly, I've been asked why C# doesn't allow you to define your own operators.
There are some languages that allow you to do that, but that's very much not what
Re-reading this, I'm not sure it's terribly insightful, so I'll try to summarize.
When you're designing a language, you need to be clear up front what you're trying
to build, and who is going to want to use that. Those early decisions are going to
have a huge impact on the design of the language, and once you've made them, you can't
really go back.
Today, I accidentally figured out that the "off" button on my XBox isn't just an off
button. It's also an on button, and it's one that doesn't eject the disc first, so
you don't have to wait for the tray to come out and push it back in.
Today, I participated in the Tacoma Wheelmen's Heritage Century,
a ride through the picturesque Enumclaw valley. Normally, I would have added "in the
shadow of Mt. Rainier", but since it was overcast, the mountain was hidden.
I had hoped to do the whole century (100 miles), but because I got sick a couple of
times this summer and injured recently, it wasn't going to happen. I settled for a
shorter version. Overall, a pretty good ride. It was much hillier than I had expected.
Luckily, I've been suffering on hills for weeks. At one point, I was following
a guy up a steep hill - so steep that I had to stand up even though I was in my lowest
gear, and during the highest part of the power stroke, my back wheel was spinning
up. I put that in the "not fun" category, because if it slips hard, I'm probably going
When I got to the top, I realized I was following a guy with an artificial leg from
the knee down on the right side. I'm used to being passed, but usually the people
I'm passed by have all their parts. Pretty amazing.
After I finished that section, I caught up with my wife and daughter, who were doing
the 45 mile route with my daughter on her Burley Trailercycle.
I hooked her onto my bike for the next 9 miles, and then when we switched back, I
found a nice slight downhill and cranked it up to 20-23 MPH for a few miles, and then
cruised across the flats to the finish.
Overall, I'm pretty happy. My legs hurt but never got to the cramp stage, I had enough
energy for the whole ride, and my butt didn't start hurting until I'd been riding
3.5 hours. Next year my target is RSVP.
Distance: 63.5 miles
Average speed: 13.9 MPH
Pedal Revolutions: 22,100
Cows: N (where N >> 1000)
Food: 3 Power bar balance (600 calories), 3 fig newtons (165 calories), 2 energy gell
packets (200 calories), 1 1/2 bananas (150 calories), 32 oz gatorade (240 calories).
Total = 1355 calories
Calories used: Approximately 600 cal/hour ~~ 3000 calories used.
column is live on MSDN. This one shows the socket-based peer-to-peer system that
I built for my ongoing music scheduling project. As you may or may not know, there
is no support for serialization on the compact framework, so I had to build my own.
It ended being pretty cool.
In other news, last week one of my previous column made the from page on microsoft.com.
First time for that.
Today I set a new record in the amount of time I spent on a single email.
I've been trying to coordinate a change in how generics work. Ultimately, this will
involve coordinating with about 10 teams to figure out how to make a breaking change
without breaking the build (which is a pretty big in in the VS team), but for now,
I'm just working to get the process started. To do that, I need to write an email
that explains what problem we're trying to solve and how to solve it.
I wrote the first verison of the email at about 9 in the morning, and then got some
advice on whether I was taking the rigth approach. I repeated this process throughout
the day, interrupted by about 2 hours of meetings.
The final version was written just after 5PM, and sent right before I left. 3 hours
spent on the email, and another hour or so working on the same issue.
I sent the mail, went down to the garage, got into the car and start to drive home.
As I pulled out of the garage, The Cars "Let the Good Times Roll" came on radio. I
turned it up.
"Let them leave you up in the air"
"Let them brush your rock and roll hair"
While it's no longer cool to drive around in your car with the windows open listening
to "The Cars" and 1978 was a long time ago, you can still sit in the leather
seats of you 328, turn up the air conditioning, and cruise home. I've probably listened
to this album as much as any in my collection, but it remains on of my favorites.
Have a great weekend.
Last week, I made a bad joke (I'm the owner of bad jokes for the Visual C# PM team),
related to the the concept of arity in generics. I regret that I don't remember the
exact joke I made, but we riffed a bit on different permutations (popul-arity, singul-arity,
disp-arity). That went on for a few minutes, but we realized that it ws a tough joke
Then Julian (one of our IDE PMs) suggested that we could communicate it better through
code. Here's what he suggested:
Once you've done this, then people can discuss the Hil-arity and Jocul-arity of
You may have noticed that we often don't aspire to particularly high standards of
If you ever want to find words that contain a certain string of letters, I suggest OneLook.
The C# team has finally decided who is going to PDC, and I'm going to California,
though I am not going to make a new start, nor do I current have an "achin'" in my
(1) Too lazy to do a google search, huh? Too young to know better. Okay, just this
My daughter just started a new science unit in her 4th grade class. After she explained
it at dinner tonight, I told her a story that I thought I'd share with you.
One day, a farmer got up, got dressed and went outside to the barn. He got out his
tractor and took it out to his alfalfa field, which he needed to plow under after
He spent the whole day plowing, and finished the field. He turned his tractor around
at headed for home, but as he reached the edge of the field, it mysteriously stopped.
He backed up, and tried again. And again. No matter what he tried, he could not get
out of the field. He left the tractor and walked home.
The next morning, he got up, called the John Deere repair service, and sat down to
wait. At 10AM, the mechanic arrived, and they walked out to the field. The mechanic
patiently listened to the farmer's story, shook his head, and started walking away
from the field.
"What are you leaving for?", said the farmer. "You haven't fixed it".
"There's nothing wrong with the tractor", the mechanic replied. "You've got a magnetic
After I told that, my daughter rolled her eyes and went back to eating. She does that
I have a couple of recommendations to make, from my experience buying a used BMW 328i
The first is for my broker, Darrel Kempf. Darrel
ended up owning a very small car lot (4 cars) when he bought some property a number
of years ago, and that somehow turned into a business selling, renting, and brokering
Darrel was recommended to us by a friend that bought a 530 though him. For a flat
rate ($600 in my case, IIRC), he will find a used car for you and transport it back
to his lot, where you pick it up. In my case, he ended up travelling to a BMW auction
in California and then talking to me about the cars that were available on his cell
phone as he walked through the car lot. Overall, a very pleasurable experience, and
I figure we saved at least $4000 on the car over what it would have cost in Bellevue.
He deals in all makes and models of cars.
My second recommendation is for Carfax. After
Darrel had bought the car and before I paid for it, I ordered a Carfax vehicle history
report for $19.99. It told me that there had been no severe accidents reported, that
the odomenter was likely correct, and that it had only had one owner. It also gives
the history of when it entered the US, when it was licensed and emission tested, etc.
Easily worth the money for the peace of mind.
With PDC coming up, there have been lots
of Microsoft entries about what makes a good presentation, and I'd like to throw
my 35 cents into the discussion. Here are three things I like to keep in mind.
Why is always more important than what
Technical people are smart and used to figuring out things on their own. They can
figure out the C# property syntax in their sleep. What they can't figure out is what
was going on in your mind when you wrote a feature, and knowing that is the most
This is also critical for connecting with your audience. Showing some code and saying,
"have you ever had to write ugly code like this?", and then showing the improvement
will always garner a good response (assuming that the feature is actually useful).
It's your job to provide the connection between the feature and the problem it solves.
What you don't talk about is more important than what you do talk about
Technical topics always have lots of subtle and interesting points that you could
talk about. Understand the difference between what you could talk
about and what the audience needs to know, and stick with the simplest scenario to
start with. I've seen lots of presentations where the speaker throws in "interesting"
asides that merely confuse the attendee.
To put it another way, your job as a speaker is to filter the important information
out of all the possible information. If you don't filter out the irrelevant details,
your attendees won't know whether they should understand that information. That will
1) leave them thinking about your previous aside when you want them thinking about
the topic you're now discussion and 2) make them feel stupid.
Your job is not to display your technical mastery of the subject. I don't, for example,
talk about the advanced events syntax when I talk about C# events. It's not relevant
Get concrete fast
Real world examples always beat abstract ones. Don't spend time on introductions when
you could explain it as part of a real-world example, or show as part of a demo
Iterate and embellish
Most topics have several layers to them, either layers of complexity or ordered layers
of discussion. In properties, for example, I would first show the world without properties,
discuss the problems, and then show the world with properties. A building-block approach
is easier for people to understand, and it builds the progression into the presentation
so you can't forget it.
I once came across a presentation guide that suggested not using revelation in presentations
(revelation is when points are gradually revealed). If you're going to present effectively,
you need to be able to focus the discussion on a specific point, and you do this through
revelation. If you have three main points on a slide, and you show them all at once,
your audience will be reading the second and third points while you're talking about
the first. You want them listening to you instead.
Revelation combined with diagrams can be a tremendous learning aid. A good diagram
is worth at least 2^10 words. Consider whether you can express points graphically.
Finally, I have a personal reason for liking revelation. One of the reason I
emjoy presentating is the comedic potential, and an essential element of humor
is timing. The funny part of the slide usually isn't the first part, and
if you don't use revelation, everybody gets to it at different points - if they
notice it at all. You want the impact to hit them all at once, and that's why you
You should also read Conference
Presentation Judo by Mark-Jason Dominus. If you presented before,
this is a phenomenally useful presentation. Make sure you read the notes along
with the slides.
And if you're a Microsoft person who wants somebody to comment on your slides, I might
Roy Osherove writes of some very
interesting research in his blog.
I've always found research about how we read to be fascinating
Over the past few years, we've gotten lots of suggestions and questions about the
C# language, and we haven't done a very good job responding to them, for a variety
The first reason is that we haven't devoted as much time as we probably should have
to interacting with customers on the subject of language design. That's something
I'll be trying to improve in the next few months. You can expect to see some more
information about new language features before we give out bits at PDC.
The second is a bit harder to explain. Basically, it revolves around whether a feature
fits into what I'll call, for want of a better term, "The C# Philosophy". Some of
the philosophy can be reduced to guidelines or rules, such as "Simplicity is also
a feature", but there remains a fair portion that is really just based on the informed
judgement of those on the design team. On some issues, that can make it
really hard to communicate why we made a specific decision, as it's hard to put into
words how we make our choices.. In the words of one of the design team members,
"it took me 6 months of design meetings before I stopped making a fool of myself".
For me, I think it was close to a year.
So I don't expect the communication to be perfect. But it should be a lot better.
I'm hoping to devote a number of entries to some of the guidelines we use. Note that
this is really on my view of the philosophy of the design team, so don't view this
as the definitive view. Guidelines I hope to cover:
I'll try to do one of these each week.
I've been home sick today, so I didn't get to post this until now.
Today is "Talk like a Pirate" day