I often end up in a situation where I want to discourage other developers from continuing to use a method or class. For example, let's say I have two library methods "A" and "B" where "A" is the "old" way of doing some task and "B" is the "new" way of doing that task. In many cases, A and B are sufficiently different to make refactoring code using A to start using B non-trivial (e. g. requires flowing through of additional state). Since A works in the cases where it's used, I don't want to prioritize the refactor. I do, however, want to give my fellow developers a visual indication that A is not to be used in new code.
Thus, I'd ideally like the strike-through you get when referencing a member with the ObsoleteAttribute
WITHOUT the associated compiler warning/error (since turning that on would emit hundreds of errors from all the old uses of A that we don't plan to address any time soon). That way, if a developer writes a new line of code with A, he or she will immediately notice the strike-through and fix the code to use B.
Is there any way to get such functionality in VisualStudio (2012)?
EDIT:
There have been several comments to the effect of "there's no way to distinguish between new and old code". I agree. However, that's not what I'm asking for, so let me clarify: instead, what I want is a visual representation of code being "out of date" (e. g. strikethrough) without the corresponding compiler warning or error. That way, developers in the process of reading old code or writing new code will get an immediate visual indication that something is out of date. Even if this isn't supported natively in .NET, maybe there is a VS extension out there for this purpose?
There have been several comments to the effect of "you can't both have a warning and not have a warning". I thought I explained the use case above, but I'll give it another try. We have a set of core libraries which are used heavily throughout the various solutions that comprise our code base. Sometimes, I make an update to one of these libraries which provides a new, better API for performing some task. To maintain backwards compatibility, I can't just remove the old way of doing that task (in many cases), since tons of existing code relies on using the old set of APIs and can't be trivially refactored to use the new one. Furthermore, there's no pressing reason to do so; it would just risk introducing bugs into existing code. However, I'd like some way of visually alerting developers to the fact that certain APIs should be avoided in favor of other ones. This is difficult, since developers tend to learn how to accomplish some task by reading existing code that accomplishes the same task. That makes new APIs hard to spread, since the old entrenched APIs are referenced by so much existing code. The ObsoleteAttribute
achieves this via compiler warnings, but those warnings will just create tons of noise from the hundreds of existing uses of the old APIs. That's why I like the strikethrough: it's something that is very visual and yet it will only intrude on a developer when he or she is reading or writing code that uses an out of date API. Here are some examples of changes where I wanted to mark an old API:
As a further note, I think the answer to this question does a good job of describing why you might not mark something obsolete even though you wouldn't recommend using it in new code.
There are several comments/answers simply calling out the existence of the ObsoleteAttribute
. Please note that the text of this question has always referenced that attribute.
To mark a method as deprecated we can use the JavaDoc @deprecated tag. This is what we did since the beginning of Java. But when a new metadata support introduced to the Java language we can also use annotation. The annotation for marking method as deprecated is @Depreated .
How can I make a method Obsolete? We can make a method obsolete by putting [Obsolete] attribute on the top of the method.
You need to use the [Obsolete] attribute. Example: [Obsolete("Not used any more", true)] public class MyDeprecatedClass { //... }
Adding the Obsolete attribute to your method will give the strikethrough in intellisense.
[ObsoleteAttribute("This property is obsolete. Use NewProperty instead.", false)]
public static string OldProperty
{ get { return "The old property value."; } }
To disable the warnings add this before the attribute:
#pragma warning disable 612, 618
And to reenable:
#pragma warning restore 612, 618
As noted here, putting a ignore in your project file instead of in your code would be a very clean solution.
<WarningsNotAsErrors>618</WarningsNotAsErrors>
EDIT: Also, check out @JonHanna's answer about using the EditorBrowsable
attribute.
As others have noted, there are actually 2 warnings that are thrown with the obsolete attribute.
EDIT:
#pragma warning disable 612, 618
[Obsolete]
#pragma warning restore 612, 618
public class test1
{...
When you try to use test1
you will get:
Note that when you type var test = new test1()
the strikethrough does not occur.
But test1 test = new test1()
will show the strikethrough.
So you want a warning, but without any warnings?
The main problem here, is there's nothing that upon compilation distinguishes "old code, before we thought better of it" from "new code, that shouldn't use the old habits"; it's all just code.
About the only thing you could do is to use the ObsoleteAttribute
and then use #pragma warning disable 612, 618
on the current uses. As always, #pragma warning
should never exist without a comment:
#pragma warning 612, 618 //This block of code uses BadOldMethod(), code review planned
/* ... code here */
#pragma warning restore 612, 618
Of course, if there's a good reason to stop using it, there's a good reason to make that review sooner, rather than later.
Edit: Oops, I forgot about 612 as well as 618. You can set the attribute to raise 619 instead of 618, but that can't be disabled (one of the main reasons for setting it, is that that sometimes suits).
A further discouragement can come from marking the member as [EditorBrowsable(EditorBrowsableState.Never)]
. The fact that the method won't show up in intellisense at all, while the new one will, would encourage people toward the new one (as long as the library is referenced as a library rather than as a project within the solution, or a class within the same project).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With