What to do about “interop” methods in WinFX

Tomorrow we have a WinFX API review for some of the windows shell team’s APIs.  On one of the classes I see this set of overloads:

        public DialogResult ShowDialog();

        public DialogResult ShowDialog(Window parentWindow);

        public DialogResult ShowDialog(IWin32Window parentWindow);

        public DialogResult ShowDialog(System.Windows.Forms.Form parentForm);


My worry is in the bottom two.  They are clearly for interop with HWnd and WinForms, which I think is really great to have.  In fact, we need more of these kinds of interop methods in WinFX to help developers transition over.  Nevertheless, I am worried that they are “gunking-up” the public API.  That is they are in a super discoverable place but they do not need to be super discoverable.  People using the APIs are likely to be more advanced users that don’t need it “in their face”.  Where they are now everyone will have to wide through the list of overloads in Intellesense, docs, etc.  


I plan to suggest they remove them from this class and create a static class in some interop namespace such as:


namespace System.Windows.Controls.Interop {

    public static class ContactPickerDialogHelpers {

      public static DialogResult ShowDialog(IWin32Window parentWindow, ContactPickerDialog dialog);

      public static DialogResult ShowDialog(System.Windows.Forms.Form parentForm, ContactPickerDialog dialog);




The pattern occurs over and over again in the platform, do you think my suggestion is a good fix.  Other thoughts or comments?

Comments (29)

  1. Shane King says:

    Why don’t you just put a filter on intellisense and the docs so that the methods don’t show up by default, but can be made to show up if you want them to?

    Sounds like a cleaner and easier to use solution to me.

  2. Drew Marsh says:

    Put them on an interface like IInteropWindow (not a great name, but illustrates the point) and implement them explicitly. Then only people that need to deal with interop will have to deal with that interface, everyone else is kept clean.

  3. Judah H. says:

    I like your idea Brad. Putting it in such a public place adds to clutter. By putting such controls in the interop, you’re cleaning up the public stuff. Additionally, people who are going to do a lot of interop for their project can find it quicly by going to the said namespace. I like it.

  4. Brad Abrams says:

    Wow — great feedback so fast.. thanks!

    Filtering is hard… the settings are combersum, hard to know how to express the docs, what do you do with books, etc.

    The explicit interface implementation is not a bad idea, but you still end up with some hard connection between the old world and the new world. That is NewWorldType has to implement OldWorldInterface. Not the end of the world, but I was hoping for something a little cleaner.

    Yup, I do think people will find them in that interop namespace — thanks!

  5. MartinJ says:

    So, instead of NewWorldType implements OldWorldInterface, you have AnotherNewWorldType connects to NewWorldType to give you OldWorldFunctionality. The hard connection is still there, to me.

    Are you planning on discontinuing support for OldWorldFunctionality? You break those clients that use that AnotherNewWorldType. Either way, you will break someone’s code. I’d rather keep functionality in one place. That helper class doesn’t add anything special.

    Yeah, you could have a helper class that "converts" between IWin32Window, Form and Window. This helper wouldn’t know about specifc classes. That would simplify things by making the class a one-stop shopping place for backwards compat.

    public static Window Compat.ToWindow(IWin32Window parentWindow);

    public static Window Compat.ToWindow(System.Windows.Forms.Form parentWindow);

    Then, people would just use the helper class as needed wherever the Window reference is required:


    That’s what you’d be doing behind the scenes, anyway. You’ve just factored out this convertion into a useful class for everyone instead of hiding it behind a few hundred helper classes.


  6. Dan Bright says:

    While I can’t see what’s wrong with the initial solution (they are all there), I think that your solution would also be good.

    I’ve never heard someone complain about too much documentation.


  7. Ken Brubaker says:

    I’m concerned about your conventions. In .NET 1.x I saw a lot of *Utility classes. Boy, it would be really nice if you could publish more patterns like you have with *Base and *Core. When should we use *Helpers and *.Interop?

  8. I would think that creating a new attribute like

    [TransistionalAPI("This method for advanced users only ..yadda, yadda, yadda")]

    Or whatever name you come up with. Anyway, apply the attribute to the methods in question, and have the IDE filter on the attribute. If the "advanced methods" checkbox is checked, then the IDE shows them in intellisense, other wise it does not. It already does this to some extent with other things.

    Myself, I hate having methods that belong to another class placed in "helper" classes just to make things "look nice". It makes it harder to find what your looking for in the long run.

    Put in your request for the attribute BEFORE WinFX is released, and it might be in the IDE when you get ready to release it.

    Just my $.02

  9. David Bossert says:

    So you’re reducing clutter by… adding clutter? I think putting the interop members in a separate class is the *worst* thing you could do. How hard is it to just ignore those overloads, anyway? When I got started with WinForms, my head didn’t explode when I saw IWin32Window. I took a look at the interface name and the documentation, saw that it had something to do with interop, and I’ve been skimming past it it ever since. You don’t need to be Scoble on the Mountain to figure this stuff out.

    Sometimes it seems that with all this talk of Morts and Elvises, the VS.NET and MSDN teams have forgotten about another kind of developer. The kind of developer who actually reads the documentation. The kind of developer who isn’t just copying-and-pasting samples from MSDN. The kind of developer who has half a brain. If you simply must do something about interop class members, then just filter the documentation, but dumbing down the framework only makes things harder for the rest of us.

  10. Chris Nahr says:

    Sorry, nothing about the fundmantal issue here but…

    Brad: Your list of WinFX overloads for ShowDialog looks like you’ve just found a bug. System.Windows.Forms.Form already implements IWin32Window, so there shouldn’t be a need for a separate Form overload. The various ShowXyz overloads in the existing System.Windows.Forms namespace take either IWin32Window or Form, but never both in the same overload list.

  11. mihailik says:

    There is EditorBrowsable attribute to do such "hides". MSDN docs on it are clean, don’t you think so?

    If Microsoft plan is to broke as much existing code as it can, your idea is excellent choise. Just move method to other class and all we will have more time to spend digging an debugging. 🙂

    P.S. For me, I use overload with IWin32Window as much as possible.

  12. Stephane Rodriguez says:


    ShowDialog is popular enough a method to allow any kind of variations. That indeed does not apply to less popular methods and classes.

    I think using static ampers the ability to come up with the threading model of one’s choice. In other words, static are soooo c-world. 🙂

  13. Mads Houmann says:

    You should definitely try to keep the new APIs as free from references to ‘old’ APIs as possible. MartinJ’s suggestion of having a single interop wrapper class seems the best solution to me, if possible.

  14. Jim Arnold says:

    -1 for static "helpers". The framework has enough static/sealed stuff as it is. It makes testing against those APIs very difficult. Plus, as Chris says, Form implements IWin32Window anyway. Keep it OO.


  15. Paul Quinn says:

    There are several classes/methods/properties in the current api, both in WinForms & in ASP.NET that already, in the docs, state that they are only there to work with legacy (WIN32/ASP) code.

    There are 3 situations here:

    a) apis that are used to interoperate with old apis outside of the framework [Win32 -> .NET]

    b) apis within the framework where there is now a "better" way of doing things but can still be used [WinForms -> WinFX]

    c) Deprecated apis that you don’t want people to use

    It would be good to put these in seperate packages, (Interop.*), but as several classes have properties/methods that fall into these categories, this wouldn’t work. Also, case c) is covered by System.ObsoleteAttribute so it makes sense to take an approach that is similar….So, my suggestion would be:

    a) Create an enum System.LegacyPlatform with values "WIN32", "ASP", "NET1.0" etc (if something like this doesn’t exist already…)

    b) Create 2 attributes: System.InteropAttribute (point a above) and System.LegacyAttribute (point b). Both should be able to take:

    i) a message (a la ObsoleteAttribute)

    ii) a bool isError value (a la ObsoleteAttribute)

    ii) a System.LegacyPlatform value

    in their construction (I realise the word "Legacy" may be a bit contentious for point b)).

    c) Attach them to the various classes/methods/properties.

    d) Hook this into the IDE/MSDN Library etc to hide all objects that have the LegacyAttribute/ InteropAttribute/ ObsoleteAttribute attribute(s).

    e) It should be then possible, in the project build properties, to state if the build should permit any Legacy/Interop apis. If any are used, and the build is set to non-legacy, the api which has this property should have the logic to point to the developer to the appropriate non-legacy api in the build task list form its message value.

    …then, for every new release of the framework, the api would have to be reveiwed for legacy apis. But, in being able to specify a "non-legacy" build, I should be able to try to keep me code base clean going forward. It would also be nice if LegacyAttribute/ InteropAttribute/ ObsoleteAttribute also could have the same parentage…

  16. Kevin Westhead says:

    I also like Martin’s suggestion, which seems consistent with existing classes such as System.Drawing.ColorTranslator.

  17. theCoach says:

    Interop should be clearly marked as Interop. I have no idea how this stuff is mapped to physical code, but it seems possible that seperating interop might also provide space for performance gains.

    I like Brad’s suggestion — is it possible to include a wizard/helper for people that are implementing Interop, that would point them to the pit of success solution?

    If someone is doing interop, is that information available to the IDE? Can the user specify it? If so, the last item on intellisense could point to the helpers, or provide a link to a wizard for interop.

  18. James Bellinger says:

    Well, I like the idea of separating such methods into a separate class, since having to scroll through lots of overloads with no relevance in most cases (Managed DirectX is plagued with this problem) takes an awful lot of time, and those methods will be used less and less as time goes on.

    Still, I’m not sure I’m too keen on ending the class name with ‘Helpers’. It makes it sound like a disorganized group of possibly unrelated methods (it’s the plural that does it).

    Not only that, I really think, if possible, that the parameter changing on the overload should be at the end, not the beginning. It looks a lot cleaner with IntelliSense, and since it’s the dialog you’re referencing, that should come first.

  19. My preference would be to leave them where they are. I think it’s easier to ignore them in IntelliSense then it is to have to look someplace weird when you do need them.

  20. DarthPedro says:

    I think MartinJ’s idea is the best one. Remove the IWin32Window and Form overloads, but provide converters to go from those to a WindowClass.

    public static Window Compat.ToWindow(IWin32Window parentWindow);

    public static Window Compat.ToWindow(System.Windows.Forms.Form parentWindow);

    This cleans up the ShowDialog method without putting these call in an Interop class. I think that would be the worst thing to do (even worse than just having 4 overloads of that method in your class). So, even if a conversion class (like the one above) is too costly or not possible, I don’t think the methods should be moved to a separate class.

  21. Jose Simon says:

    For me MartinJ’s idea is the best one too.

  22. MartinJ says:

    Applying attributes to hide this compatibility overload methods doesn’t eliminate the problem. It leaves the underlying fault: duplicate code all over the place to convert from the older types to the preferred one. That is very un OO.

    So, being good OO people, we want to pull all this duplication out into its own class. You could use the rule that this needs to be exposed in a base class (where do you put it, the base Control class, Component, or somewhere else?). Now, every class until the end of time will have this conversion code included in it (remember, it’s a breaking change to remove a method from a class). If you put it in some other class, maybe including a bunch of other conversion routines (have you seen System.Convert lately? This is similar, only geared for a specific area instead of the entire framework), you have a single location to find these things.

    An added benefit is that you can now apply the ObsoleteAttribute to the specific methods to indicate that the conversion may not be allowable in the future. You haven’t broken any code (but, it will break at some point in the future; it’s just not clear when). You’ve warned the developer to rethink their solution to avoid this behavior.

    If you really want developers to know about this converter, add it to the text of the method’s XML documentation as "other values are possible using the Compat class" for the methods that need it (you duplicate your documentation, but not the actual codebase).

    As for complaining about making the methods static, I don’t see how it makes debugging any harder. Does explicitly instantiating an object to call a generic (not Generic) routine make it easier to test? You get the exact same functionality. I find just using a method easier. But, if you want to make sure the method works correctly, just call it, caching the return somewhere.

    private void TestMe(Window frm)


    Compat fixer = new Compat();

    Window someThing = fixer.ToWindow(this.parentThingie);



    private void TestMe2(Window frm)




    private void TestMe3(Window frm)


    Window Inst = Compat.ToWindow(this.parentThingie); //yeah, you can see if the conversion worked



    Personally, I find TestMe2 easier to get my head around, either writing or testing.


  23. mihailik says:

    > Applying attributes to hide this compatibility overload methods

    > doesn’t eliminate the problem. It leaves the underlying fault:

    > duplicate code all over the place to convert from the older types

    > to the preferred one. That is very un OO.

    This conversion must be done by MessageBox method itself, not by caller. Why programmer need to write any more code lines? This is job for library side.

    If code will contain such Win32WindowConverter calls, it will not be readable. It is some kind of ugly C++ coding style, and a step from C# simplicity.

  24. Jim Arnold says:


    (I assume you were referring to me when you said this):

    "As for complaining about making the methods static, I don’t see how it makes debugging any harder"

    I said testing, not debugging. I use mock objects a lot, which generally rely on inheritance and method overriidng. Statics can’t be overriden, sealed classes can’t be inherited. How do I test interactions with Form.ShowDialog() (for example) without using a real form? As it stands, I have to use an adapter and test against that.


  25. Keith Hill says:

    +1 for a set of WIN32 interop methods as well as a set of WindowsForms interop methods. It makes the code a bit more self-documenting IMO. It makes it clearer that I am using interop and it doesn’t needlessly clutter up things for those who don’t use interop. However, this isn’t something I would fall on my sword over. 🙂

  26. I like the idea of shuffling off the Interop to another space.

  27. B.Y. says:

    First of all, I hate the overloaded-functions-with-the-same-name thing. It makes the code and the documentation more difficult to read, and intellisense more difficult to use. I’d rather have something like this:





    Putting the last 2 in another class is a bad idea. They’re simple, useful things which should stay simple. If you put them in another class, it’ll be more difficult to find, and you’re adding annoyance to simple, straight forward things.

  28. Mark Levison says:

    +1 for the MartinJ’s idea to add pair of converters. Many of us will never use the interop and so the additional overloads would just be clutter.