'Notify Developer of a "DO NOT USE" Method

OK, I know what you're thinking, "why write a method you do not want people to use?" Right?

Well, in short, I have a class that needs to be serialized to XML. In order for the XmlSerializer to do its magic, the class must have a default, empty constructor:

public class MyClass
{
  public MyClass()
  {
    // required for xml serialization
  }
}

So, I need to have it, but I don't want people to use it, so is there any attribute that can be use to mark the method as "DO NOT USE"?

I was thinking of using the Obsolete attribute (since this can stop the build), but that just seems kinda "wrong", is there any other way of doing this, or do I need to go ahead and bite the bullet? :)

Update

OK, I have accepted Keith's answer, since I guess in my heart of hearts, I totally agree. This is why I asked the question in the first place, I don't like the notion of having the Obsolete attribute.

However...

There is still a problem, while we are being notified in intellisense, ideally, we would like to break the build, so is there any way to do this? Perhaps create a custom attribute?

More focused question has been created here.



Solution 1:[1]

If a class is [Serialisable] (i.e. it can be copied around the place as needed) the param-less constructor is needed to deserialise.

I'm guessing that you want to force your code's access to pass defaults for your properties to a parameterised constructor.

Basically you're saying that it's OK for the XmlSerializer to make a copy and then set properties, but you don't want your own code to.

To some extent I think this is over-designing.

Just add XML comments that detail what properties need initialising (and what to).

Don't use [Obsolete], because it isn't. Reserve that for genuinely deprecated methods.

Solution 2:[2]

Prior to VS2013 you could use:

[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]

so that it doesn't show up in IntelliSense. If the consumer still wants to use it they can, but it won't be as discoverable.

Keith's point about over-engineering still stands though.


Since VS2013 this feature has been removed. As noted in https://github.com/dotnet/roslyn/issues/37478 this was "by design" and apparently will not be brought back.

Solution 3:[3]

throw new ISaidDoNotUseException();

Solution 4:[4]

You could build your own Attribute derived class, say NonCallableAttribute to qualify methods, and then add to your build/CI code analysis task the check to monitor if any code is using those methods.

In my opinion, you really cannot force developers to not use the method, but you could detect when someone broke the rule as soon as possible and fix it.

Solution 5:[5]

I would actually be inclined to disagree with everyone that is advocating the use of the ObsoleteAttribute as the MSDN documentation says that:

Marking an element as obsolete informs the users that the element will be removed in future versions of the product.

Since the generic constructors for XML serialization should not be removed from the application I wouldn't apply it just in case a maintenance developer down the road is not familiar with how XML serialization works.

I have actually been using Keith's method of just noting that the constructor is used for serialization in XML documentation so that it shows up in Intellisense.

Solution 6:[6]

I read the heading and immediately thought "obsolete atribute". How about

    /// <summary>
    /// do not use
    /// </summary>
    /// <param name="item">don't pass it anything -- you shouldn't use it.</param>
    /// <returns>nothing - you shouldn't use it</returns>
    public bool Include(T item) { 
    ....

Solution 7:[7]

Separate your serializable object from your domain object.

Solution 8:[8]

Nowadays you can use code analyzers for such need - thanks to Roslyn compiler in modern .NET.

Either you can write your own code analyzer. Here are some tips to start with:

Or use some already existing - this is way I have choosen for my needs:

Here is another nice "homepage" for Roslyn Analyzers: Cybermaxs/awesome-analyzers: A curated list of .NET Compiler Platform ("Roslyn") diagnostic analyzers and code fixes. Everyone can contribute here! https://github.com/Cybermaxs/awesome-analyzers

Solution 9:[9]

Wow, that problem is bugging me too.

You also need default constructors for NHibernate, but I want to force people to NOT use C# 3.0 object initializers so that classes go through constructor code.

Solution 10:[10]

What you're looking for is the ObsoleteAttribute class:

using System;

public sealed class App {
   static void Main() {      
      // The line below causes the compiler to issue a warning:
      // 'App.SomeDeprecatedMethod()' is obsolete: 'Do not call this method.'
      SomeDeprecatedMethod();
   }

   // The method below is marked with the ObsoleteAttribute. 
   // Any code that attempts to call this method will get a warning.
   [Obsolete("Do not call this method.")]
   private static void SomeDeprecatedMethod() { }
}

Solution 11:[11]

ObsoleteAttribute will probably work in your situation - you can even cause the build to break if that method is used.

Since obsolete warnings occur at compile time, and since the reflection needed for serialization occurs at runtime, marking that method obsolete won't break serialization, but will warn developers that the method is not there to be used.

Solution 12:[12]

I'm using the ObsoleteAttribute.

But also you can have some comments of course.

And finally remove it completely if you can (don't have to maintain the compatibility with something old). That's the best way.

Solution 13:[13]

Yep there is.

I wrote this blogpost about it Working with the designer.

And here is the code:


public class MyClass
{
  [Obsolete("reason", true)]
  public MyClass()
  {
    // required for xml serialization
  }
}

Solution 14:[14]

There is already quite a lot of good answers. But I think the best option is to use serializer that can use parametrized constructor. It is not serializer you need but for example Entity Framework Core knows how to use parametrized constructors.

Entity Framework Core documentation:

If EF Core finds a parameterized constructor with parameter names and types that match those of mapped properties, then it will instead call the parameterized constructor with values for those properties and will not set each property explicitly.