The Good and the Bad: Obsoletion in the Framework


You are likely familiar with this error message:

Program.cs(969,9): warning CS0618: System.Collections.CaseInsensitiveHashCodeProvider’ is obsolete: ‘Please use StringComparer instead

 

You get it when you use a Type or member in the Framework that we have applied the ObsoleteAttribute to.  In Whidbey Beta1 there are a bunch of places (notice, many of these are pre-release noise and will not be in the final product).  In each case we have some significant improvements to the framework that we want to have a clear way to communicate to developers.   

This works great if you are working on a new app, if you happen to stumble upon using some “old” functionality you get a warning can easily move to the new stuff.

However if you are porting some very large code from V1.1 to V2.0 you could get a number of warnings about obsoleted stuff.  Because we have a very high level of backwards compatibility with the framework, in almost all cases you don’t HAVE to move to the new feature, but there are good reasons to do so.  So you could easily take an app that builds clean (no warnings) on V1.1 to 100s of warnings in V2.0 none of which HAVE to be fixed. 

 

 

So the questions for you:

1.       Have you run into this problem yet?  Do you expect you will?

2.         Do you think the value you get out of the warnings makes up for the pain of dealing with them?

3.         Are we obsoleteing too much stuff in the Framework in V2.0?

4.         Would you rather see obsoletes done via FxCop rather than in the compilers

 

 

Update: JasonZ (CLR PUM) chimes with a clear opinion on this… Love to hear your comments on his post as well…

 

Update: More feedback from TheServerSide

Comments (39)

  1. Dr. Search says:

    1. Not yet but I expect I will.

    2. I’d rather get warnings. I can always disable this specific warning through #pragma or compiler switch if I don’t like it.

    3. Is the ocean too blue green?

    4. I’d rather see compiler warnings.

  2. Definitely compiler warnings. It’s closer to the process and the sooner I know, the better.

  3. Stuart says:

    I’d love to have an easy way to mark code to ignore obsoletion warnings. I’ve encountered this moving from 1.0 to 1.1, even, and the code in question is third-party code that we don’t want to mess with. I’d love to be able to say:

    #obsolete

    // code that uses obsolete techniques

    #noobsolete

    I like the warning, but I want to be able to make the choice to supress it for a particular chunk of code (while still getting warnings if I do obsolete stuff anywhere else).

  4. Shane Courtrille says:

    1. Not yet.

    2. Warnings are always a nice thing to get. It helps make up for my lack of knowledge.

    3. Change is goodish… now if only we had a linker so we didn’t need to redistribute a 20+ MB download every time a new better version comes out 😉

    4. Alot of people don’t use FxCop. I’d rather see the warnings stay in the compiler.

  5. 1. Yes, when moving from 1.0 to 1.1. I expect I will have the same ‘problem’ with the move to 2.0.

    2. I need these warnings, as they are the best way for me to notice code that is about to break.

    3. I don’t think this is something you should even ask. The design changes are yours and if you decide that something is to be obsoleted, you should obsolete it. When I obsolete something, I don’t give excuses, I give workarounds*. Even if I don’t change the code, I can still run it on the old framework.

    4. I think that having the compiler do it is good. This way, I can’t not know about this. Some people don’t use FxCop. On the other hand, it’s good to put it as a rule in FxCop no matter what.

    I wrote about this a while back, but talked about unit testing: http://weblogs.asp.net/okloeten/archive/2004/06/28/168022.aspx

    I think your suggestion of using FxCop is better.

    * What I do want to see is a workaround for every obsoleted member. For instance if you obsolete method A, I want to see how I can get the same functionality done with the new method I have to use instead. Give me a link to msdn or something…

  6. Jeff Parker says:

    COMPILER PLEASE NO CHOICE on the matter, but actually both would be better but has to go into the compiler

    Reason #1 Main Reason and this bit me going from 1.0 to 1.1 Cause something in System.Xml wasn’t backward compatable, only found out when compiler blew up. Several thousand posts on the web showing good and great examples You never know when google will turn up some code that will show you how to do something that you need. Look in your own history for example the Brad Abrams Blog has a load of good info in it.

    Ok so you create a little test project because you need this specific code to do something. And yes I know you can use snippet compiler but thats beside the point when I really need to get something to work and I am testing it for my specific use it goes into Visual Studio. Now this is just a small test scenario. I am NOT going to run a test scenario through FX Cop I don’t care if my pseudo code proof of concept little test adheres to every FX cop rule. You don’t care you are glad it worked. So now imagine you have no idea this code that you used is obsoleted, so now you spend more time on it fitting it right into your project, getting it just right so it will pass FX Cop, Compile it, Check it in, then you go get an FX Cop report that it is obsolete.

    Reason #2 Trust me if you don’t put it in the compiler and because you asked, here and because I said I know I will do this, and I know when I do it and have this project I just got all done and I see it not passing FX Cop because something I didn;t know until I ran FX Cop. I will be back here bugging you to please fix this 😉

    Reason # 3 as usual any time I post to your blog I will include this request to put it in the compiler same as I alsways request PLEASE Fix the asp.net controls make them XHTML Compliant. (I figure sooner or later your gonna look at it)

  7. Jeff Parker says:

    Oh yeah and also because FX Cop is sometimes an automated later thing not an up front thing, Take a look at how Mike Swanson builds software on large projects.

    http://blogs.msdn.com/mswanson/archive/2004/10/05/238423.aspx

  8. I think that compiler support is a must for this case, and turning off the warning with a #pragma directive is acceptable.

    The C++ compiler has been doing this for quite some time, and it’s very useful. For example, VC++ has been warning about OLD_IOSTREAMS for quite some time, and it’s finally removed in the VC++ 7.1 compiler.

    If the compiler gives the warning, it also means that the framework team has a lot more feedback on how necessary it is to support the feature. For example, if something is deprecated, the warning gives developers an opportunity to provide MS feedback on how neccessary the feature or API is.

    It also gives the product teams ammunition for support cases – A developer certainly won’t be able to deny that you told them that it was deprecated!

  9. Paul Blamire says:

    Would definitely prefer to see the compiler raise these issues

  10. Jeff Parker says:

    Actually would prefer to see FXCop go away and get all that info at compile time. I really hate getting out of visual studio then going and running a report that basically says Nope your not going home early today get back in there and fix this.

  11. James Hancock says:

    My personal favourite was the MS Web services Extensions V2.0 obslession. Just obsolete static key encryption and then provide no sample on how to replace it with something better.

    Still can’t figure out how to do it the new way, so we’ve stayed with V1.0.

    If you’re going to obsolete it, then give us really strong sample code on how to replace the old with the new and then I’m happy. If you don’t, I’ll get relally anoyed because you’ve given me no tools to work with the new based on my knowledge of the old.

  12. Steve Krehbiel says:

    1. Yes, several places.

    2. Warnings are great. They tell me what’s changed, and I can fix everything up to use the new, better stuff quickly and without missing something.

    3. Obsolete as much as you want, as long as you are providing something better in return (and provide some info about it in the compiler warning).

    4. As others have commented, FxCop is not the place – better to have it during compile so that it’s not missed.

  13. Travis Spomer says:

    1. Yes, including in code that was generated by the WinForms designer. 🙂

    2. Absolutely, especially since the VS designers shouldn’t be generating obsolete code.

    3. Most definitely yes. When you can provide a better way of doing something, you should. As others have noted, there should be a hint in the warning pointing to what one needs to use instead.

    4. Definitely keep these things in compiler warnings. Visual Studio is an IDE… I don’t want to have to run another tool to get important information.

  14. Wagahai says:

    1. Have you run into this problem yet? Do you expect you will?

    Yes, a few times. I expect to run into it occasionally in the future as well. However, I do not think of it as a "problem", but rather an opportunity to enhance my code for the future.

    2. Do you think the value you get out of the warnings makes up for the pain of dealing with them?

    Yes, I find them very useful. I would rather update my code immediately than produce soon-to-be obsolete applications.

    3. Are we obsoleteing too much stuff in the Framework in V2.0?

    No, not at all. As long as there are concrete reasons and alternatives, obsolete as much as you need. Also, please ensure that the documentation is sufficiently updated as well.

    4. Would you rather see obsoletes done via FxCop rather than in the compilers[?]

    The compilers please. While FxCop is extremely useful, I do not run it as often as I compile.

  15. AT says:

    I’ve strong disagreement with people. FxCop is the only way to go for me?

    Why?

    a) Compile (at least debug version) used by developer very often. Adding additional logic to compile will decrease compile speed. Obsolete is one-time shot – once you know about it – it may take weeks (or even years!) to get rid of it, as well it can be impossible sometimes (for example for targeting same code base for all .NET Framework versions). This way additional 20-1000 obsolete ("You are not following best-practice!!") warnings will hide other more valuable error-like warnings.

    b) FxCop will be possible to use for non C# languages. For example VB, C++, Iron.Python and Fortran or even Java 😉

    Single application will provide a consistent and up-to-date best practice analyzer for all applications targeting .NET Framework.

    c) FxCop is extensible. In contrast – C# compiler (and I expect a lot of others) nope. You will be able to add own corporate standards to it. For example complete reverse to obsolete attribute – "VeryNewFunctionalyAttribute(sting message, URL helpUrl)" to indicate a API that non-tested well or will be non-compatible with prior versions of application.

    Something like:

    VeryNewFunctionaly("XML config file support were recently added to our 400+ developers codebase and may result in some currently unknown issues. We expose this API early to make it possible to use it actively in future without needs to update all applications. It’s highly recommended to use old config file format.", "www.mycorp.intranet/development/XMLConfig.html")

    Nothing like this you will be able to express on compiler level.

    d) It will be hard (if not impossible) to suppress select obsolete warnings at compile time – this will requere using some crazy directives or flags. But suppressing warnings in FxCop as easy as one mouse click on exclude button and providing comments.

    e) Getting warning at compile _time_ does not mean that you have this must be done by _compilers_. I really like Microsoft idea of FxCop integration into Whidbey IDE. This way person will not see any difference between compiler warnings and FxCop warnings. I think this confused most of people who posted comments here.

    They were thinking that question 4 mean: "Would you rather see obsoletes done via standalone application rather than in the IDE", but it does not this. No way.

    f) But using FxCop as standalone application provides benefits to users. If you will get application/libraries assemblies from third-party – you will be able to check if they follow best practice recommendations from Microsoft – or nope. This can be a major purchase decision maker will motivate developers/product managers to follow best practice – instead of ignoring them. Currently if you ignore Microsoft best practice recommendations – no one force can motivate you to reconsider this. Usage of standalone "FxCop: .NET Application compatibility testing" and application verifier (from http://www.microsoft.com/windows/appcompatibility/appverifier.mspx ) by your potential customers/buyers will motivate you.

    If you will move all those obsolete warnings to compiler – you will possibly decrease amount of information available to end-users.

    I hope that I did not miss any major issues with using FxCop integrated into Integrated Development Enviroment.

    The only tiny issue I’m aware – is possibly weak implementation of integration. IMHO, this is the only risk that can prevent World happiness to happen 😉

    But I hope that Microsoft teams will be able to do their job well.

    If you are still reading this – Thanks 😉

  16. David Levine says:

    Create another attribute that makes it clear that the warning is because the original code could cause problems – security, bugs, whatever. Have a different obsolete attribute that signals that the original code was ok but a new-and-improved class/method/etc. is available. One type I can safely ignore and the other should never be ignored.

    The real distinction is between a change that constitutes an improvement (minor warning) and the other signals that a flaw is present (major warning). This is a distinction that the creator of the library can most easily determine.

  17. RichB says:

    My experience this time around is no different from when I moved from .Net 1.0 Beta1 to RTM, and from RTM to Everett. I think ObsoleteAttribute warnings are great – so much so that I use them myself whenever I refactor my own code – If I think a method isn’t used and it’s complicated to determine whether that’s really the case (eg the method is in a library used by many apps), then I mark it with the ObsoleteAttribute for a few weeks. If after that time I’ve not come across any warnings then I delete it.

    This nicely parallels how I often work with files and documents on my hard disk. If I think a file is obsolete, I will usually move it to an obsolete folder first – this acts a bit like a long-term Recycle Bin and also works on file servers.

    As an aside, I agree with Jeff Parker that having some static analysis in the compiler and other static analysis in FxCop is a division I would rather not see. I love all the static analysis and want it to be done FAST at compile time.

  18. Kevin Daly says:

    I may be being naive (God knows it wouldn’t be the first time) but a compiler switch to disable/enable the warnings seems like a good idea.

  19. Steve Saxon says:

    I’d very much like to see [Obsolete] messages come out of the warnings.

    Visual Studio does already support an analog to [Obsolete] through the //! TODO style comments, which to me serve a very similar purpose (that of telling me about things I need to go back and fix)

    Perhaps the compiler could be convinced to stream obsolete messages in such a way that Visual Studio would display them as message alongside the //! TODO comments, and not in the warning stream.

    One side request to this would be: why not allow the compiler to similarly capture and emit the //! TODO comments to that same stream. It would be useful for projects doing automated builds (such as Windows Longhorn!) to have these cleanup items going to a log that could be periodically reviewed.

  20. Hey Kevin, there is a switch to turn off the warning: csc /nowarn:0618

  21. AT says:

    😉 BTW, I forgot to add – Obsoletion is bad for end-users. Fixing all thouse obsolete warning will render project impossible to compile for older versions of framework and will force people to upgrade or install additional software.

    Thus – then you will release .NET Framework 3.0 and will obsolete a few 2.0 APIs – then developer will be unable to separate obsoletion warnings for 1.1 -> 2.0 vs. 2.0 -> 3.0 . But developer willing to develop project on 3.0 – because this is the only framework version supported by IDE (take a look on Whidbey – only 2.0 support – no way to develop for 1.0 or 1.1), but after development – run NAnt build scripts and distribute 2.0 (or 1.1) compatible binaries.

    Versioning for obsolete warnings are a must (in addition to severity and problem type).

    <joke lame="true">

    Obsolete involve some kind of conspiration. Using obsoletion will render Sales department happy.

    </joke>

  22. Marius Sundbakken says:

    1. No, not yet. I expect I will.

    2. Yes, absolutely.

    3. Probably not, but if massive changes to existing APIs continue to happen, it may be an indication of a process problem. Someone is apparently not thinking things through. API stability is overrated. If it was that important, where are all the great new, say, MFC applications?

    4. I’m not sure. I don’t have a big problem with it being handled in the compiler, but where does the line go between FxCop and the compiler? It’s more of a philosofical question, but answering it could provide a guideline.

  23. Someone pointed out to me that this situation is not dissimilar to the following warning the C# compiler gives:

    public class Foo {

    public static void Main () {

    long l = 4l;

    Console.WriteLine (l);

    }

    }

    foo.cs(6,17): warning CS0078: The ‘l’ suffix is easily confused with the digit

    ‘1’ — use ‘L’ for clarity

  24. marklio says:

    1. I have not encountered this enough to label it a problem. We use ObsoleteAttribute quite a bit internally on our projects, and at times we’ve generated more warnings that I was really comfortable with. They tend to mask other more important &quot;shorter-term&quot; warnings.
    <br>2. The value is definitely worth it, especially considering the pain can easily be resolved by fixing the warnings or ignoring them with a switch.
    <br>3. Not in my opinion. They all seem to have a rational decision behind them.
    <br>4. I think pushing obsoletes to FxCop is a step too far. Unfortunately, for many (perhaps the majority of) .NET developers, this would remove their visibility completely. I believe the compiler is in the right position to provide the visibility. FxCop could shed some additional light by suggesting more specific &quot;fixes&quot; for individual members than a compiler warning could or should. This of course is more work to manage.
    <br>Another suggestion…I think the IDE could also help us here by organizing the warnings with appropriate priorities, so something like accidentally hiding a virtual member gets more visibility than member X not being supported in a decade.

  25. AT says:

    Brad: "warning CS0078: The ‘l’ suffix" is impossible to detect on IL level using FxCop.

    This mean that something like CheckStyle (http://checkstyle.sourceforge.net/) can be created for .NET

    A few people agree with me http://www.stuartwoodward.com/tech/archives/000399.html

    P.S> In contrast from suggestions to not use compiler for suggestions – IBM Jikes Java compiler (http://oss.software.ibm.com/developerworks/opensource/jikes/) has implementation of "Effective Java" (http://java.sun.com/docs/books/effective/ ) pedantic warnings (+Peffective-java)

  26. Yes, today FXCop would have trouble with this, but there is nothing to say it could not grow to understand source code in the future… But good point on that pedantic warnings mode…

  27. Timothy Fries says:

    I’d like to see an attribute that generates a compiler warning *like* ObsoleteAttribute, but doesn’t include any prefix text in the warning — a general CompilerWarningAttribute.

    In our development process, sometimes methods get pushed out to the repository before they’re ready; it’d be nice to be able to have an unambiguous way of warning users of those methods that they’re not quite ready yet — the only effective way to warn them is via out-of-band documentation, which not everyone reads; or with a not-quite-appropriate obsolete message.

  28. Joe White says:

    I like the Obsolete attribute. I think it’s a bug that it has a parameterless constructor, though; anyone who adds the attribute somewhere should always give a helpful message. Maybe the parameterless constructor could be flagged with the ObsoleteAttribute. (grin)

    Like someone else already mentioned, I use Obsolete in my own code for refactoring purposes. Since I’m not on Whidbey yet, ObsoleteAttribute makes a very useful "Find References".

    I disagree about //!TODO, because that only works for files that you currently have open in the editor. I seldom use TODO comments because they go away when I close files. Obsolete keeps reminding me to fix stuff. This is good.

    I’ll second the CompilerWarningAttribute suggestion.

    Someone made the point that the Obsolete warnings get in the way of spotting other warnings. This is a valid point. Delphi has long had *three* levels of compiler messages: errors, warnings, and hints. Perhaps C# could do the same thing, and Obsolete could be a hint? After a compile, you would still see that you had 0 errors and 0 warnings.

    Oh, and:

    1. Yes (though in Delphi, not in .NET).

    2. Yes.

    3. Don’t know.

    4. No, keep them in the compiler.

  29. Daniel says:

    Java was pretty liberal with deprecating APIs and I never minded it a bit. I am happy to move my code to a better API and I appreciate obseletions letting me know when a better option is available.

    However, you would have to have pretty strong motivations for *removing* an obseleted API (i.e., breaking binary compatibility). That would cause pain.

  30. JoeW says:

    It would be great if the compiler and the IDE could work together here to make the whole process of upgrading easier.

    Why not extend the obselete attribute so that you could match off the old method/property with the new one. In many cases properties and methods are simply moved around or just renamed. If the Obselete attribute provided all this data the IDE could display a hyperlink in the warnings list asking "Would you like to fix your reference to obselete MethodXXX to new MethodYYY"? Just think of all the names that don’t comply with the design guidelines in the existing framework – all could be automatically converted to the new names with any intervention from the developer.

    I could see this working much like the SQL Server client suggesting new indexes based on query plan results.

  31. Tim Haughton says:

    Quite an easy decision for me. I would have to go for compile time warnings. I’d also like to see some finer granularity in the project settings so that I could opt at some point to be able to select the type of warnings that are promoted to errors.

    Or perhaps it should be an assemblyinfo thing. A version compliance attribute applied to the assembly. That might be kinda cool.

    But it should definitely stay as compiler warnings, and in no way should it be bumped to FxCop. You’d be suprised just how many developers don’t know what it is. Seriously.

  32. A reader recently asked if applications built against Beta2 will run when RTM comes out. &amp;nbsp;The short…