Welcome to MSDN Blogs Sign in | Join | Help
Implement interface in Whidbey

Shaykat, another PM on the C# team, recently posted (http://blogs.msdn.com/shaykatc/archive/2004/03/10/87582.aspx) a VS 2003 tip for automatically implementing an interface.  We have received almost universally positive feedback about it, but there were definitely some gotchas:

  • It works quite well for implicitly implementing an interface for the first time, but it's not reentrant with an easy interaction (you almost always have to delete and re-type the interface name), such that if you add additional members to an interface it's hard to use the feature to implement stubs for those.
  • In 2003 we attempted to intelligently choose whether to implement the interface implicitly or explicitly.  If there were existing members with the same name but a different signature then we would implement that member explicitly.  Unfortunately we weren't entirely consistent so you'd occasionally end up with code that wouldn't build.  That type of implicit vs. explicit inference also turned out to be a bug farm.
  • The code spit that we chose for generating the stubs is sub-optimal.  It would determine the return type and return either null if it was a reference type, or a default value for a value type (if it was a known value type like int, then it would return 0; if it was unknown then it would return “new ValueTypeName();“).  Unfortunately this means that you can write code against these interface members and have the code 'work', even though there is no backing implementation.  This is occasionally useful, but we've had lots of requests to throw a NotImplementedException instead.
  • There was no way to modify the code spit.  You couldn't add or remove TODO comments, for example.

We have attempted to tackle all of these issues in Whidbey.  In order to invoke this feature in Whidbey you'll use an editor 'smart tag'.  This tag is a little marker that appears underneath an interface name when the cursor is on the same line in which it appears.  It can be invoked through the keyboard or by hovering the mouse over the marker.  After invocation a context like menu will appear, which in this case, will offer two options.  To either implement the interface implicitly, or explicitly. 

Shows the highlighted marker under IComparable
Shows the expanded menu giving a choice between implicit and explicit implementations

You've probably already determined how this addressees the first two issues.  First, the smart tag is always available, so if you add additional members to an interface then it's easy to invoke the feature again and generate the additional stubs.  Second, we no longer attempt to determine whether to implement the interface explicitly or implicitly, instead we leave that decision in the hands of the developer (where it belongs). 

The code generation bullets are interesting, because there are a lot of features in Whidbey that generate code in some manner.  Given that, we decided to leverage our expansions feature (I'll blog about this separately if you haven't read about it elsewhere yet) to allow developers to modify the generated code.  For example, the implement interface feature uses an expansion that looks like this:

<Declarations>
  <Literal
>
    <ID>signature</ID
>
    <Default>signature</Default
>
  </Literal
>
  <Literal
>
    <ID>NotImplementedException</ID
>
    <Function>SimpleTypeName(global::System.NotImplementedException)</Function
>
  </Literal
>
</Declarations
>
<Code Language="CSharp" Format="CData"
>
<![CDATA[
$signature$
{
throw new $NotImplementedException$();
}
]]>
</Code>

The $signature$ literal is replaced when the code is generated.  To put a comment in every generated method stub, you would just add it to this file.  The $NotImplementedException$ literal is worth mentioning as well.  Its replacement value is determined by a function.  In this case, the function “SimpleTypeName” is used, which determines what the 'simplest' form of global::System.NotImplementedException is.  That is, if you were to implement an interface in a context with no using directives, it would insert System.NotImplementedException; however, if you were to implement the same interface in a scope in which the System namespace had been imported then it would use 'throw NotImplementedException()'.

Posted: Saturday, March 13, 2004 3:36 PM by AnsonH

Comments

jaybaz_MS's WebLog said:

# March 15, 2004 2:12 PM

Dan Fernandez's Blog said:

# March 15, 2004 4:02 PM

Jeff Key said:

# March 15, 2004 9:49 PM

Scott Munro said:

Sounds great. I blogged on my thoughts for how we should be passing arguments to refactorings and the ways that we will be initiating them.

Do you have any thoughts on Intelliarguments and Refactoring Initiations?
http://dotnetjunkies.com/WebLog/scottmunro/archive/2004/03/14/9066.aspx
# March 16, 2004 2:13 AM

Eric Gunnerson's C# Compendium said:

# March 16, 2004 1:57 PM

Roland Weigelt said:

The most annoying problem I have with the "implement interface" feature is that I have to copy the documentation comments manually. I blogged about this here:
http://weblogs.asp.net/rweigelt/archive/2004/03/10/87449.aspx
# March 16, 2004 3:20 PM

Omer van Kloeten said:

I'm assuming there's a key combniation for either one so that I don't have to use my mouse...
# March 17, 2004 9:03 AM

Vrye Bredo said:

While thinking about these refactoring etc, I have to ask, when can iSpeak theCode and refactor etc pointing my finger or pen at touch/drawing screen? Graphic artists have long used screens you can draw on, i'm just waiting for the interface where you can transform the 'inaudible speech' to code without having to speak it out loud.
# March 18, 2004 6:16 AM

Andrew Deren said:

would be nice to have option not to generate #regions. I hate it when it generates the interface and then I use arrow keys to scroll down and the region collapses.
Would also be nice to be able to regenerate new methods (maybe it's in whidbey already?)
When I add method declarations to interfaces then I could easly add those to my classes.

If you're looking for a really good example of refactoring you should look at eclipse (I bet you get that alot)
One really nice feature is when you compile you get little icons in the gutter with common fixes. For example if a class is missing a method from interface (or abstract class) you can choose to add this method (or make the class abstract).
There are many other things they do good, that would be nice to have in VS.
# March 19, 2004 11:51 AM

Red Forks said:

Looks good!
But I hate use mouse when keyin code.
How about simply popup a menu, then use up/down, enter/esc keys?
Popup menu easily support both mouse & keyboard.
SmartTag is useful in mouse-orianted enviroments, such as excel or web browser.
# March 19, 2004 7:15 PM

Red Forks said:

Looks good!
But I hate use mouse when keyin code.
How about simply popup a menu, then use up/down, enter/esc keys?
Popup menu easily support both mouse & keyboard.
SmartTag is useful in mouse-orianted enviroments, such as excel or web browser.
# March 19, 2004 7:20 PM

aBlogByGus said:

# March 22, 2004 12:37 AM

aBlogByGus said:

# March 22, 2004 12:42 AM

CorneliuT said:

Hi,

How about 2 new autocomplete types:
1. Auto complete Enums
2. Auto complete declarations;
I see both quite big coding performance enhancements that should be part of the IntelliSense.

However most of the times your project is getting big and have enumerations declared in lots of namespaces that are not necessary all imported.
Thus, I would like to be able to just write:
this.Dock =
and in this momment the Intellisense should help me by writing the partial/full namespace+enumeration name for me like this:
this.Dock = System.Windows.Forms.DockStyle
so I just press the "." and write select the value I need.
The autocomplete could be triggerd like the one for delegates using the TAB key after you write the "+=".

I think is would extremly nice and helpfull to have especially when working on large projects where you can't remember all the enumerations from all the namespaces.

2. Auto complete declarations;
For the declarations IntelliSense should work the same by providing you the option to press tab and complete the name of the class you need to declare in that point:
eg: I have a collection: myapp.ns1.ns2.ns3.MyObjectsCollection and an instance myobjects.
To do an add I have to write:
myObjects.Add ( new myapp.ns1.ns2.ns3.MyObject () );
I would like to write only:
myObjects.Add (
press TAB and get:
myObjects.Add ( new myapp.ns1.ns2.ns3.MyObject (
This would be very nice also.
It could also work on the righthand side of an operations eg:
instead of writing:
myapp.ns1.ns2.ns3.MyObject newObj = myObjects[ 0 ];
I would like to write
myObjects[ 0 ];
move the cursor at the begining, insert an "=" and press TAB or something similar and get:
myapp.ns1.ns2.ns3.MyObject = myObjects[ 0 ];

This would be trully nice :)

Anybody else cares about this two functionalities ?

Thanks,
Corneliu.
# March 25, 2004 8:05 PM

Sam Gentile's Blog said:

# April 2, 2004 8:52 AM

Sam Gentile's Blog said:

# April 2, 2004 8:52 AM

Staffan Gustafsson said:

In general, I really hope that everyone on the team working with completion has toyed at least a little bit with JetBrains IntelliJ. They really do set the standard for smartness in an editor. If you get close to that, you've done a great job!

If you surpass them? WOW!

/S

# April 9, 2004 2:17 AM

Code/Tea/Etc... said:

# May 14, 2004 4:39 AM

aWorkBlogByGus said:

# January 8, 2005 5:04 AM

bokka said:

Thank you fpr you.I want copy this site.

# March 21, 2007 4:12 AM

aWorkBlogByGus said:

Update (1/31/08): It looks like Snippy has now found a home on CodePlex . I haven't been maintaining

# January 31, 2008 1:51 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

  
Enter Code Here: Required

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Page view tracker