Is it a good practice to use the [Obsolete] attribute to instruct developers no to use parts of an API
Asked Answered
G

1

7

Recently I have been writing some serializable object that also deals with specific logic and has specific life-cycle. In order for it to work properly, it has to be instantiated with an appropriate constructor, that takes mandatory arguments. For serialization purposes, however, I must also add a public default constructor.

The object will be publicly available by our API and 3rd party developers should be able to instantiate and use it. Although there will be an appropriate documentation for how to correctly manipulate with that object, it is no guarantee that someone will be tempted to use the incorrect constructor - and then have trouble.

I am looking for a neat way to apply some guidance while the 3rd party developers are writing their code. The Obsolete attribute came to my mind - I could annotate the serialization constructor with an appropriate comment as a message. The message will then appear in the output warnings and direct the developer to the right line of code. Also, the constructor usage will get appropriately highlighted by both Visual Studio and any code inspection add-on used.

What is bothering me in this approach is that the purpose of the Obsolete attribute is quite different. It's semantical meaning is that the decorated item is deprecated and will probably be removed in further versions. In the serialization constructor scenario this is wrong, and there will be a discrepancy between the usage and meaning of this attribute. Not to mention the option "treat warnings as errors" that might be enabled in some development departments...

So, the question is - is it a an acceptable practice for such usage of the attribute? Are there any other legal and universal ways to achieve the same effect (by universal I mean not relying on 3rd party code inspection add-ons and etc. - I do not control who uses the code and what is their setup) ?


In regards to the comments in the answer below, (which is still useful to me), I must clarify that I am using a protected default constructor on an inheritable class. The constructor is there to support XML serialization, but should not be used for initializing the class in business logic. Inheriting classes should call some of the other base constructors and developers writing the inherited classes need to know that. Still, the developers deriving from this code must also have the means to enable XML serialization for their inherited classes if needed.

Goethite answered 10/2, 2013 at 14:45 Comment(2)
It's not quite the same thing, but using the [EditorBrowsable(EditorBrowsableState.Never)] will hide the constructor from intellisense to prevent a developer to get it as a suggestion and using it by mistake without checking the docs.Hachmann
@fsimonazzi, thanks for the useful information. In the same fashion nobody can prevent an obsolete member from being accessed by user code, so your suggestion is quite valid, and more in-place.Goethite
F
3

Hm, I don't think that this is a good solution. However, do you really need a default constructor?

Note that the serialization API has methods to create uninitialized instances without using a constructor at all (see MSDN: FormatterServices.GetUninitializedObject).

Also, the normal custom serialization constructor is not a default constructor but one taking a SerializationInfo and a StreamingContext. If you have some custom serialization, you may also be able to solve your issue by making the default constructor internal and apply a InternalsVisibleToAttribute for the assembly performing the serialization.

Fiddler answered 10/2, 2013 at 14:52 Comment(1)
To clarify on the deserialization issue, I was addressing not the binary (default), but the XML serialization that is part of the .NET framework. It needs parameterless constructor. The constructor is not needed to be public, but if the class is to be inherited and must preserve serialization capabilities, the constructor should be at least protected (unless of, course, if some of the other constructors work for you, but that is not a case of the question issue).Goethite

© 2022 - 2024 — McMap. All rights reserved.