.NET (the CLR) was the third generation of Microsoft's Component Object Model (COM), which in the early days referred to as the "COM+ runtime". Microsoft Visual Basic and the COM/ActiveX controls market has had much more influence on the specific CLR architectural compatability choices than Borland Delphi. (Admittedly the fact that that Delphi had adopted ActiveX controls certainly helped grow the ActiveX ecosystem, but COM/ActiveX existed before Delphi)
COM's architecture was worked out in C (not C++) and focused on interfaces, rather than classes. Furthermore supported object composition, meaning that a COM object could in fact be made up of several different objects, with the IUnknown interface linking them together. But IUnknown had no role in COM object creation, which was designed to be as language-independent as possible. Object creation was generally handled by IClassFactory, and reflection by ITypeLibrary and related interfaces. This separation of concerns was independent of implementation language, and the features of each core COM interface were kept minimal and orthogonal.
So as a result of the popularity of COM and ActiveX controls, .NET architecture was built to support on the COM IUnknown, IClassFactory, and ITypeLibrary. In COM, these interfaces were not necessarily on the same object, so lumping these together didn't necessarily make sense.
Outside the world of Visual Studio, where developers expect everything to happen automagically, grep
ing source code is a usual practice, and it actually works very well.
The problem with Visual Studio's refactoring tools is that they give a false sense of security by making you feel safe when changing code, while you can easily introduce regressions in any but simplest pieces of code. Even in languages such as C#, there are at least two very popular things which will screw with automated refactoring: Reflection and dynamic
. Should I mention what happens when you trust a tool to do a simple rename in a language such as JavaScript?
At the same time, grep
and a bit of code exploration will hardly be tricked by Reflection or dynamic
. Since grep
is barely returning the occurrences of a given string, it doesn't care whether this string represents a name of a variable, or occurs in a string, or a comment. It's up to you, as a developer, to determine whether an occurrence is actually referring to the variable you're currently renaming, or something different. Clean code with well-chosen names of variables helps tremendously.
Back to Visual Studio, the rename tool is not limited to code. You can use it as well as a smart grep
, which not only knows about the structure of your code, but also searches within strings and comments, and only that; if you're renaming Cost
class to Price
, you don't want to rename Costs
in your code, thus limiting the search to strings and comments is actually very clever:
Rename can be used to change the names in comments and in strings and to change the declarations and calls of an identifier.
Source: MSDN
All you have to do is, during renaming, to:
Select the Search in Comments check box.
But why isn't there a syntax which makes it possible to put cref
in in-code comments? While this question would better be answered by Microsoft's developers themselves, I could imagine a few reasons:
XML comments syntax, as it is implemented for C#, is quite user-unfriendly, and inherits the user-unfriendliness of XML.
Heck, even Visual Studio doesn't support the full syntax (for instance, what happened to <see langword />
, that is, by the way, one of the most used features, given the official formulation of boolean methods “Returns <see langword="true" /> whether something; otherwise, <see langword="false" />.” or the number of “<see langword="null" />” one has to put in methods who take by-reference types in parameters?!)
In most projects I've seen, nobody even cares about cref
ing classes and members in XML comments. The ones who actually care are the ones who develop libraries and frameworks which are expected to be reused, and expected to have auto-generated documentation.
The primary goal of XML comments, after all, is not to make comments refactor-friendly, but to (1) generate documentation and (2) magically provide documentation seamlessly within Visual Studio through tooltips.
In-code comments, however, are never used this way. Thus, the incentive to spend time writing XML tags becomes extremely low.
Referencing the public classes and members within the method doesn't happen on daily basis. While XML comments are public documentation, and cross-referencing there is a particularly valuable tool, in-code comments are barely explaining something about the code which is unclear for the reader. Therefore, most comments will rather limit themselves to explaining the algorithm itself (or the hack), within the scope of the method itself.
On occasions, the comment within the method will, however, talk about class members like this:
// While walking through the sequence, it should be necessary to prevent the
// caller from removing elements of the sequence when `Cleanup` is being
// called. Therefore, before the loop starts, I set `this.lockSequence` to
// `true`, while `Cleanup` checks this variable before doing its job.
However, explaining the poor implementation of a locking mechanism, the comment refers not to the public member of the class, but a private bool lockSequence
; this makes sense here, but would create an inconsistency with XML documentation which cannot refer to private members.
Best Answer
A combination of the suggested solutions:
This should clarify the intended usage to colleagues (and my future self).
<see>
-tag to increase the reference count for the constructor/method.This makes that code lens and find references show that the constructor/method is referenced.
UsedImplicitlyAttribute
[UsedImplicitly]
has precisely the intended semantics.PM>
Install-Package JetBrains.Annotations
.SupressMessageAttribute
for the messageCA1811: Avoid uncalled private code
.For example:
The solution confers the intended use of the constructor to both human readers and to the 3 static code analysis systems most used with C# and Visual Studio.
The downside is that both a comment and one or two annotations might seem a bit redundant.