Skip to content

Latest commit

 

History

History
96 lines (70 loc) · 2.94 KB

Adding Optional Parameters in Public API.md

File metadata and controls

96 lines (70 loc) · 2.94 KB

Adding optional parameters to public methods

Roslyn has strict requirements for maintaining source and binary API compatibility across minor version releases. Adding overloads of existing methods can be an effective way of adding to the public API without breaking backwards compatibility. However, overloads involving optional parameters can be tricky to make both source and binary compatible. The following steps should be followed when adding optional parameters to public methods.

Steps for adding optional parameters to an existing method

  1. Check to see if there is already a method marked with the comment

    // <Previous release> BACKCOMPAT OVERLOAD -- DO NOT TOUCH
    
  2. If it does not:

    1. Copy the method and make any existing optional parameters mandatory.
    2. Change the body to call the original method.
    3. Add the comment // <Previous release> BACKCOMPAT OVERLOAD -- DO NOT TOUCH. This method provides binary compatibility with assemblies compiled against the previous APIs.
  3. Add your new parameter with a default value to the end of the original method. This provides source compatibility to consumers of the previous API.

Examples

Before:

    public void O(string o1 = null, string o2 = null)
    {
    }

After:

    public void O(string o1 = null, string o2 = null, bool o3 = false)
    {
    }

    // 1.0 BACKCOMPAT OVERLOAD -- DO NOT TOUCH
    public void O(string o1, string o2)
    {
        O(o1, o2, o3: false);
    }

Things to avoid

DO NOT add a parameter in the middle of existing optional parameters

    public void O(string o1 = null, bool o4 = false, string o2 = null, bool o3 = false, bool o5 = false)
    {
    }

This breaks source compat when certain arguments to a method call are skipped, like O(null, null, o5: true);

DO NOT add multiple overloads with optional parameters

    public void O(string o1 = null, string o2 = null, bool o3 = false)
    {
    }

    // 1.0 BACKCOMPAT OVERLOAD -- DO NOT TOUCH
    public void O(string o1 = null, string o2 = null)
    {
         O(o1, o2, o3: false);
    }

Aside from the fact that this is often ambiguous and it won’t compile, it makes verifying compatibility much harder.

End Result

The resulting code should 1) have only one overload with optional parameters, which 2) has the most parameters of all the overloads, and 3) all previous overloads should still exist, properly commented with their release version, and contain only mandatory parameters.

NOTE

After this change, if Public API Analyzer complains about it, you should copy the entry for your change from PublicAPI.Shipped.txt and then put that entry in PublicAPI.Unshipped.txt with *REMOVED* prefix.

PublicAPI.Shipped.txt

Example.O(string o1 = null, string o2 = null) -> void

PublicAPI.Unshipped.txt

*REMOVED*Example.O(string o1 = null, string o2 = null) -> void