Ways to Synchronize Interface and Implementation Comments in C#

Ways to synchronize interface and implementation comments in C#

You can do this quite easily using the Microsoft Sandcastle (or NDoc) inheritdoc tag. It's not officially supported by the specification, but custom tags are perfectly acceptable, and indeed Microsoft chose to copy this (and one or two other tags) from NDoc when they created Sandcastle.

/// <inheritdoc/>
/// <remarks>
/// You can still specify all the normal XML tags here, and they will
/// overwrite inherited ones accordingly.
/// </remarks>
public void MethodImplementingInterfaceMethod(string foo, int bar)
{
//
}

Here is the help page from the Sandcastle Help File Builder GUI, which describes its usage in full.

(Of course, this isn't specifically "synchronisation", as your question mentions, but it would seem to be exactly what you're looking for nonetheless.)

As a note, this sounds like a perfectly fair idea to me, though I've observed that some people think you should always respecify comments in derived and implemented classes. (I've actually done it myself in documenting one of my libraries and I haven't see any problems whatsoever.) There's almost always no reason for the comments to differ at all, so why not just inherit and do it the easy way?

Edit: Regarding your update, Sandcastle can also take care of that for you. Sandcastle can output a modified version of the actual XML file it uses for input, which means you can distribute this modified version along with your library DLL instead of the one built directly by Visual Studio, which means you have the comments in intellisense as well as the documentation file (CHM, whatever).

Comment the interface, implementation or both?

As a general rule, I use the same DRY (Don't Repeat Yourself) principle as with code:

  • on interface, document the interface
  • on implementation, document the implementation specifics

Java specific: when documenting the implementation, use {@inheritDoc} tag to "include" javadocs from the interface.

For more information:

  • Official javadoc documentation
  • Some unofficial advice.

Inheriting comments from an interface in an implementing class?

GhostDoc does exactly that. For methods which aren't inherited, it tries to create a description out of the name.

FlingThing() becomes "Flings the Thing"

Where to use synchronized methods in C# : Interfaces or implementations?

It does no good on the interface, because MethodImplAttribute is itself marked AttributeUsageAttribute.Inherited = false

But this is an anti-pattern anyway, the documentation says

Locking on the instance or on the type, as with the Synchronized flag, is not recommended for public types, because code other than your own can take locks on public types and instances. This might cause deadlocks or other synchronization problems.

Instead implementations should lock (if not internally threadsafe) on an instance of object which is private to the class.

The problems of declarative synchronization are well-known -- it leads to lock order inversions -- and so the recommendation against using it is universal.

Can implementation classes inherit XML comments from their implemented interfaces?

This feature does not exist currently in Visual Studio.

You can get third party tools, such as GhostDoc that will help with creating XML documentation. GhostDoc also has the option to generate documentation that was "inherited" like you are attempting to do.

Link: GhostDoc

Infrastructure - both sync & async interface & implementation?

When implementing a library/infrastructure, and the user of this API would want to use the code both synchronously & asynchronously

Ideally, each API in your library should either be naturally synchronous or naturally asynchronous. I recommend exposing only the most natural API. I.e., if your library needs to do I/O, it could choose to only expose an asynchronous API.

Is there an elegant way to avoid code (or more accurately "flow") duplication for sync & async implementations, which would obviously bubble down to the whole call hierarchy?

I've not found an ideal solution for this. The closest I've come is the boolean argument hack, where you have asynchronous and synchronous APIs both forward to an internal method that takes a bool sync argument. This internal method has an asynchronous signature (returning a Task/Task<T>), but if sync is true, it always returns a completed task.

This ends up looking like this:

interface IMyInterface 
{
void Foo();
Task FooAsync();
}

class MyImplementation1 : IMyInterface
{
public void Foo() => Foo(sync: true).GetAwaiter().GetResult();
public Task FooAsync() => Foo(sync: false);

private async Task Foo(bool sync)
{
// Pass `sync` along to all methods that can be sync or async.
await OtherMethod1(sync);
await OtherMethod2(sync);
await OtherMethod3(sync);
await OtherMethod4(sync);
}

private async Task OtherMethod1(bool sync)
{
// When you have to choose sync/async APIs of other classes, then choose based on `sync`.
if (sync)
Thread.Sleep(1000); // synchronous placeholder
else
await Task.Delay(1000); // asynchronous placeholder
}
}

Synchronous implementation of interface that returns Task

If you really do want to do the work synchronously, you know that your async method will always run synchronously, and that's desirable in the situation, then by all means, ignore the warning. If you understand what the warning is telling you and feel that the action it is describing is correct, then it's not a problem. There's a reason it's a warning and not an error after all.

Of course, the other option is to just not make the method async and to simply use Task.FromResult to return an already completed task instead. It would change the error handling semantics (unless you also catch all exceptions and wrap them into a task that you return) so at least be mindful of that. If you really want exceptions to be propagated through the resulting Task, it may be worth leaving the method async and just suppressing the warning.



Related Topics



Leave a reply



Submit