PDC Tips and Tricks
A few months ago I was in LA speaking at PDC 2005. I was absolutely astounded by the amount of excitement that the LINQ project generated. I haven’t been working on LINQ anywhere near as much as some of the other members of the team, but I’m happy to say I got to help out a bit with some of the content that we delivered at PDC (notably the hands on labs). Outside of the LINQ project announcement the C# team actually had two additional sessions. One was on debugging ASP.NET applications, given by Habib, and the other was on Tips & Tricks for the Visual C# 2005 IDE which I gave. The presentation was a ‘lunch’ session, which is a new style of presentation that we were trying this year. The idea is that attendees sacrifice a bit of their lunch time, grab a boxed lunch, and learn about a technology that is either shipping or close to shipping (the majority of PDC content is focused on future technology). The most interesting aspect of this style of presentation is that at any point during the presentation attendees should be able to leave or enter and still end up getting useful information out of the presentation. Organizing a presentation in which it’s okay to walk in and out was a bit of a challenge, particularly since I still wanted it to flow in a meaningful way. Ultimately we decided that the vast majority of the lunch sessions should be ‘tips and tricks’ to facilitate that goal.
The IDE session went well (outside of some troubles the day before with a rogue hard drive), and a number of folks mentioned that the tips would be very useful when they got back to work and started using 2005 again. Virtually any one of the tips that I presented could actually have a blog entry of its own, and maybe if I find some time at some point I’ll actually do that; however, for the moment I wanted to post a recap of the tips that I gave for people that couldn’t attend PDC. It’s also possible to watch a recorded version of the presentation here.
The presentation is broken down into four sections which represent the various meta- tasks that happen when developing software, particularly in the edit, compile, debug cycle (we don’t include test, document, design, etc. in these presentations at the moment). The four sections are understanding, modifying, writing, and debugging code. Imagine that you’re given a new code base to work on and you’re asked to add a feature. In order to do that, you’ll probably start by spending time trying to understand what the code does and how it works. After you’ve done that, you’ll likely have to modify it in order to make the feature that you’re working on fit in the product in a natural way. Then you’ll spend some time actually writing the feature, and ultimately, unless you’ve gotten it right the first time, you’ll spend some time debugging it. I’ve listed the tips that I gave in the presentation below categorized into those four sections.
I hope they are helpful!
Understanding Code
Tip #1: Class designer
This is less of a tip and more of a suggestion. When dealing with a new code base it’s often a good idea to get a high level view of how classes interrelate. It is sometimes possible to do this through specs and architecture diagrams, but those are often out of date (if they exist at all). As an alternative, it’s possible to use the Class Designer, included in VSTS, to build up those relationships on a diagram. That diagram can then be persisted as part of the project and serve a similar purpose for anyone in the future facing the same problem. The nice thing about the Class Diagram is that it’s just a view on the source code, such that changing either the diagram or the source will update the other.
To access the Class Designer a Class Diagram must be added to the project.
- Right-click on the project node
- Select Add | New Item
- Choose "Class Diagram" which is in the bottom right
- Name the diagram and click "Add"
It’s possible to add a Class Diagram to the project from other entry points as well, including the context menu of Solution Explorer.
The Class Designer interacts with Solution Explorer, Class View, and Toolbox. Solution Explorer and Class View are the two that are most often used when understanding code; Toolbox is used when laying a diagram to generate code. You can drag types onto the diagram from Class View, which ultimately shows them as shapes. Right-clicking on the shapes gives a number of options to quickly build up an inheritance or association view of the types in the project.
For example, a simple example of the associations might look like:
In this case VectorObject is an abstract base class (so it has a dotted outline) of the Model class. The chevrons in the upper right hand corner of the shapes allow them to be expanded to show the type’s members (like Model and AnimationFrame) or collapsed to hide them (like Int32 and VectorObject). The relationship shown between Model and AnimationFrame is what’s known as a ‘collection association’ which can be used for arrays or generic collections. In this case animationSequences is a field of Model of type AnimationFrame[]. The final relationship is a simple association relationship; FramesPerSecond is of type Int32 in AnimationFrame. The interesting aspect of this one is that Int32 is actually a framework type loaded from metadata.
Tip#2: Keyboard bindings
I talk a lot about keyboard bindings in the presentation. With Visual Studio 2005 there are number of different keyboard ‘schemes’ that ship out of the box. Those keyboard schemes are initially dependent on the Settings that are chosen the very first time that Visual Studio 2005 is run. These can be reset or changes via the Tools | Import/Export Settings dialog. In this presentation the keyboard bindings to which I refer are the Visual C# keyboard bindings which were created to give a consistent set of themed bindings so that there were patterns to learn. For example, all of the tool windows in Visual Studio now have chorded keybindings that start with Ctrl+W.
So, Class View is bound to Ctrl+W, C. It’s also bound to Ctrl+W, Ctrl+C to make it easier to type.
Tip#3: Add New Item dialog selection
The Add New Item dialog (Ctrl+Shift+A) has been changed a bit from 2003. The most notable change is the addition of a number of templates. That makes it more difficult to navigate; however, the behavior has been changed to match that of explorer windows. If you simply start typing the full name of the item that you’d like to use then the selection will move there. For example, typing “C” will select “Class”, but type “Cr” will select “Crystal Report”. In 2003 the selected template was based off of the first letter of the word typed. So, typing “C” would select “Class” and typing “Cr” would select “Class” then select “Resources File.”
Tip#4: Class view customization
The Class View has additional configuration options over and above what it had in 2003. These are accessible from the toolbar:
If you’re using the next tip it’s important that “Show Project References” is checked.
Tip#5: Examining the framework
A question that we get a lot from new users of the framework is what concrete implementations exist for Stream. The Class Designer can actually help solve this type of question, and indeed, help explore the inheritance relationships in metadata a namespace at a time. This can be done by simply dragging an entire namespace from the “Project References” node in Class View onto the diagram. For example, dragging System.IO from mscorlib, would look like this (when zoomed in on the stream type):
Tip#6: Class View search
Class View has been changed significantly since VS 2003, but I think that the most useful addition is the ability to “filter” the list of types down to what is typed in the combo box at the top of the tool window. This is particularly useful when used with the keybinding Ctrl+K, Ctrl+V which puts focus in that combo box (even if you’re current focus is the editor). Then it’s as simple as typing in the name of the type to find and then hitting enter to navigate.
Tip#7: Goto definition
This is one that a lot of folks may already know from VS 2003, but it’s extremely useful so it’s worth mentioning. A number of times when trying to understand code it’s worth looking at each line of a particular method. Inevitably that method will create a new type, or call another method, etc. and it will be necessary to find out more information about them. In order to do that, you can use “Goto definition” via the keyboard binding F12 and that will navigate you to the declaration of that method, type, local, etc.
Tip#8: Collapse to definitions
A lot of times when C++ programmers start using C# they often ask for a high level view of the source code; a quick way to find out the members, fields, and such that a class has (like a header file). It’s possible to use Class View or Class Diagram to get this view, but that takes you out of source pretty quickly. An alternative is to use a command we call ‘Collapse to definitions’, which is bound to Ctrl+M, Ctrl+O. That command collapses all of the regions in the file and makes it significantly easier to skip over the implementation.
Once the file is in a collapsed state it’s often useful to simply edit a particular collapsed block. There is a “Toggle Outlining” command, which is bound to Ctrl+M, Ctrl+M, which will either expand or collapse an outlining region depending on its current state. It’s equivalent to using the little plus sign on the side of the editor, but doesn’t require using the mouse.
Tip#9: Navigation stacks
There aren’t all that many people that know Visual Studio actually has more then one navigation stack. There is a general navigation stack that is exposed by the editor. There are various heuristics that are used to track ‘interesting’ points that should be put onto that navigation stack. That navigation stack is exposed through the ‘Text Editor’ toolbar. Backward is bound to Ctrl+- and Forward is bound to Ctrl+Shift+-. This navigation stack works well in a lot of cases, but when using Goto Definition to drill in to a particular piece of code it’s often useful to irrefutably say ‘go back to the last place I invoked Goto Definition from.’ This can be accomplished by hitting Ctrl+*. This works in both 2003 and 2005. In 2005 you can also use Ctrl+& to navigate to the destination of the last Goto Definition invocation.
The ‘Goto Definition’ specific navigation stack is also, in 2005 C#, bound to extended mouse buttons on an Explorer mouse.
Tip#10: Find all references
Goto Definition is extremely useful, but it’s really only half the story. If you’re on a definition or a reference and you’d like to find all other references then it would be nice if there was a quick command to do so. In 2003 there was a command called “Goto Reference”, which many developers pointed out was pretty nonsensical since there is virtually always more then a single reference. What many developers didn’t know is that after invoking Goto Reference it was possible to iterate through the remaining references by using Ctrl+Shift+1 and Ctrl+Shift+2. To be fair, we made that pretty much impossible to discover. The second question people always ask is what reference Goto Reference picks in 2003; the answer is that it picks one at random.
In 2005 that’s changed significantly and now we show a results list when “Find All References” is invoked. The keyboard command for Find All References is Shift+F12, which makes sense since it’s the inversion of Goto Definition. The nice thing about the list is that it’s possible to do non-linear searches, and that it’s easy to see how many references actually exist.
Tip#11: List iteration
There are a number of tool windows in Visual Studio that contain lists of information. The Error List, Task List, Find Symbol Results, Find All References, and the Output Window. All of the items in these tool windows can be iterated through using F8. Imagine that you’ve just done Find All References using Shift+F12. You can then simply hit F8 from the editor and navigate to each reference, you’re focus will stay in the editor. It’s very useful for compile errors as well.
Modifying Code
Tip#12: Close all but this
In 2005 the menu for the document tabs in Visual Studio has been updated to include a command called ‘Close all but this.’ This is extremely useful if you’ve been editing code for a long while and the number of documents that you have open is large, but you still want to be editing the current file… well, you get the idea. Simply right click on the tab of the file that you want to remain open:
Copy Full Path and Open Containing Folder are also very useful if you need to do file management outside of VS.
Another quick note for the tabs is that if you middle click on the tab then it closes just that tab. It’s a more local way to close the current document then scrolling over to the [x] if you’d rather use the mouse (instead of Ctrl+F4).
Tip#13: FxCop integration
A question that we often get is whether or not there are any tools in VS 2005 that will help detect whether or not a piece of code needs to be refactored. The tool support isn’t expansive, but the integration of FxCop (a static analysis tool originally released on GotDotNet which runs over IL and reports violations of an extensible rule set) provides a good starting point. There are two rule sets that ship in the box, Naming and Maintainability, that can help identify where to use the Rename and Extract Method refactorings.
To customize the FxCop integration:
- Right-click on the project node in Solution Explorer and select Properties
- On the bottom left there will be a tab called "Code Analysis," select it
- A page that will allow the rule sets to be selected will appear on the right
To run the FXCop integration simply go to the Build menu and select:
The violations will be reported in the error list.
Tip#14: Smart tags
In VS 2005 there is a common idiom used throughout the environment that we call smart tags. They appear in the editor as small markers, orange or blue, after an action is performed which indicates a ‘next step’. For example, changing the name of an existing element will provide a smart tag marker that would perform a rename refactoring.
The tip here is simply that Ctrl+. is bound to the command that invokes the smart tag menu, so in order to perform the action it’s often as easy as hitting Ctrl+. and then <Enter>.
Tip#15: Solution explorer entry point for rename
A common style that we see C# developers’ use is to have a single type per file. If a rename refactoring is invoked from source, and you’re changing the name of the type that exists in that file, then it’s easy for these to get out of sync and for 2 steps to be taken every time the name of a type is updated. If, instead, the rename of the file is performed first then assuming that the namespace name is the same as the project (plus the folder structure) and the name of the file is the same as the name of the type, a prompt will appear allowing a rename refactoring of the type to be performed as well.
Tip#16: Keybindings for refactorings
The keybindings for refactorings use the chord Ctrl+R. So, Extract Method is bound to Ctrl+R, Ctrl+M, while Rename is bound to Ctrl+R, Ctrl+R, etc.
Writing Code
Tip#17: Window | Close all documents
In both 2003 and 2005 a quick way to close all of the documents that are open in the editor is to use the “Close all documents” command. This command is available off of the Window menu in the editor.
Tip#18: Code snippet customization
I expect that a number of people reading this already know what Code Snippets are so I won’t spend much time on them. However, the tip here is that Code Snippets are completely customizable, including the ones that are shipped in the box. In order to edit them there are two important directories. The first directory is Program Files\Microsoft Visual Studio 8\VC#\Snippets\1033\ which contains the set of Code Snippets that are shipped in the box. The Visual C# directory contains the common expansion code snippets, like ‘class’, ‘prop’, etc. The Refactoring directory contains the snippets that are used for code generation. The second interesting directory is My Documents\Visual Studio 2005\Code Snippets\Visual C#\My Code Snippets which is where we expect most snippets restricted to a single user to live.
There is a good base for the format of the snippet files here.
Tip#19: Code Snippet Insertion
There are a few ways that Code Snippets can be inserted. Either they can be inserted into the editor by simply typing the full name of the ‘shortcut’ (defined in the schema) and hitting <tab>, or by using the Code Snippet Picker which is invoked via the keyboard binding Ctrl+K, Ctrl+X, or via the Surround With command which is invoked after you’ve made a selection via the keyboard binding Ctrl+K, Ctrl+S.
After a snippet is inserted then the fields (the areas of text that have a green background) can be navigated between by using <TAB>. When you’ve finished replacing the fields with the text that you want them to have, you can use <Enter> to ‘commit’ the snippet such that the fields go away.
Tip#20: Generate method stub
The tip for generate method stub is simply that when you’re writing code it’s often a better idea to use generate method stub to get a method with a correct signature as opposed to extract method. Extract method is more useful when the code is already written and you’re simply trying to simplify different parts of it. The reason is that for the signature of extract method to be correct it needs to know the usage of the variables both before and after where the method is called, which may not be available if you’re still writing the code.
Generate method stub itself is a feature that allows a method call to be written prior to the declaration and then to have that declaration inferred from the call itself.
Tip#21: Customization of the completion list
The C# editor provides a number of customization points, but the ones that we have received the most feedback on effect completion list behavior. The tip here is simply that the customizations are available in different scenarios from the Tools | Options | Text Editor | C# | IntelliSense page:
1. The completion list appears too often and interferes with what you’re trying to type. You’d like to revert to the 2003 completion list behavior. Simply toggle this option:
2. The completion list appears when you want it to, but it completes the wrong words. This happens when the thing being typed hasn’t been declared yet. You can customize the set of characters on which the word will be inserted and the completion list dismissed with these options:
Tip#22: Add using
This tip is pretty simple. If you know the name of the type that you want to add, but you don’t have a using for it yet, simply type the name. A smart tag will appear and allow you to either fully qualify it or add it to the top of your file.
Debugging Code
Tip#23: Stepping behavior customization
It’s often the case that when debugging code you’ll end up in a situation in which you’d like to step into a method, but the argument to the method contains property evaluations. For example:
In this case Salary is a simple property which returns a backing field of the Employee. I would never want to step into that getter because it will always do exactly the same thing. It would be nice if there was a way to tell the debugger that so that you don’t have to step in, step out, and then step in again in order to get into the IncreaseSalary method.
It runs out that there are a set of attributes that can configure different aspects of debugging behavior. One of those attributes controls stepping behavior and is called System.Diagnostrics.DebuggerStepThrough(). If we were to write the code for Salary as follows:
public decimal Salary { [DebuggerStepThrough()] get { return salary; } }
The debugger will never step into it. This can be added to a property generation snippet such that every property that is generated has this behavior by default.
Tip#24: Value column customization
The value column in the debugger data windows (watch window, locals, autos, etc.) is pretty valuable space. Ideally it will always contain information that will help move you closer to figuring out what the problem with your code is, or at least the current state of your code. Unfortunately the debugger can’t always do a good job figuring out what should be displayed in that column. For example:
static void Main(string[] args) { List<Employee> employees = new List<Employee>(); employees.AddRange(new Employee[] { new Employee("Anson Horton", 100.00m), new Employee("Luke Hoban", 200.00m), new Employee("Raj Pai", 300.00m) }); }Expanding employees in the watch window would appear as:
At this point if you wanted to know more information about ‘Raj’ it would be necessary to drill in to each of the items in order to find out where he’s stored (obviously in this example the list is ordered, so it’s not that complicated :-]). However, it would be nice if instead of the “{Employee}” in the value column we saw the name of the employee instead.
This is possible by overriding ToString in the Employee class. The debugger by default will evaluate ToString calls to give a better view in the value column. If, however, you’ve already overridden ToString to do something else, you don’t want to have a function call happen on your object, or you don’t have the source, there is another option.
It’s possible to use an attribute called System.Diagnostics.DebuggerDisplayAttribute to do the same thing. The attribute takes a specially formatted string. Basically any text that appears in the string will appear verbatim in the value column; however, you can use braces {} to escape expressions that should be evaluated in the context of the current object. For example:
[DebuggerDisplay("{name}")] class Employee {This would modify the display above such that it appeared as:
In this case Employee has a field called name that is being evaluated (as denoted by the braces).
Tip#25: Customizing the framework types display with DebuggerDisplay
As I alluded to above it’s possible to use DebuggerDisplay on framework types as well. This is done by passing in the named parameter “Target.” There is a file called autoexp.cs that appears in the My Documents\Visual Studio 2005\Visualizers directory. This has a number of examples of how to apply DebuggerDisplay. For example:
[assembly: DebuggerDisplay(@"\{Color = {color}}", Target = typeof(SolidBrush))]When the Target named parameter is used, the attribute should be put on the assembly as opposed to on a type. The assembly should then be built and placed into the directory mentioned above (hence autoexp.dll), which is how the debugger finds and loads it.
Tip#26: Hiding members from the debugger
When using properties that simply return a backing field a data window in the debugger often looks like this:
In this case we see name as both a property and a field. Ideally to reduce clutter and allow ourselves to find the important information faster, we wouldn’t show properties that currently only return the field. This can be accomplished using the System.Diagnostics.DebuggerBrowsable attribute. Simply put it on the member that shouldn’t be shown and pass in a state of Never:
[
DebuggerBrowsable
(DebuggerBrowsableState.Never)] public string Name { get { return name; } }Now the display will appear as:
Tip#27: Datatip opacity
In VS 2005 data tips have been changed such that they can be expanded. That is, it’s possible to drill into complex objects directly in the editor instead of using only the tool windows.
The only problem is that with complex objects it can quickly become difficult to see the code underneath if you want to quickly glance at it. The tip here is to hit the Ctrl key which will make the data tips close to transparent:
Comments
- Anonymous
December 13, 2005
Awesome tips! - Anonymous
June 12, 2006
PingBack from https://blogs.msdn.com:443/karenliu/archive/2006/06/12/628756.aspx - Anonymous
June 12, 2006
The comment has been removed - Anonymous
July 03, 2006
Well I must admit that I learnt a lot getting this session together and as promised here is a summary... - Anonymous
October 18, 2006
I learned some new things here. Thanks for your post! - Anonymous
December 17, 2006
While all these feature are cool, you can also try the tool NDepend to:-> browse code with a top-down approach-> obtain statistic information about your code-> produce documentation from the existing code-> audit code quality-> levelize your code by finding and removing dependency cyclesand much more.www.NDepend.com - Anonymous
November 25, 2007
PingBack from http://feeds.maxblog.eu/item_675954.html - Anonymous
December 07, 2007
The comment has been removed - Anonymous
June 05, 2008
A few months ago I was in LA speaking at PDC 2005. I was absolutely astounded by the amount of excitement that the LINQ project generated. I haven’t been working on LINQ anywhere near as much as some of the other members of the team, but I’m happy to - Anonymous
June 17, 2009
PingBack from http://pooltoysite.info/story.php?id=9730