How to document overloaded methods with the same XML comments? - c#

I know there are questions like this, but they're old. So I'm creating a new one.
At the moment when there are 3 overloaded methods I have to do this:
/// <summary>
/// Description that described summary of an overloaded method.
/// </summary>
/// <param name="fileName">Description that describes filename parameter</param>
/// <param name="options">Description that describes options parameter</param>
/// <returns>Description of what method returns</returns>
public bool ReadFrom(string fileName, ReaderOptions options = null) {
return false;
}
/// <summary>
/// Description that described summary of an overloaded method.
/// </summary>
/// <param name="stream">Description that describes stream parameter</param>
/// <param name="options">Description that describes options parameter</param>
/// <returns>Description of what method returns</returns>
public bool ReadFrom(Stream stream, ReaderOptions options = null) {
return false;
}
/// <summary>
/// Description that described summary of an overloaded method.
/// </summary>
/// <param name="rawData">Description that describes rawData parameter</param>
/// <param name="options">Description that describes options parameter</param>
/// <returns>Description of what method returns</returns>
public bool ReadFrom(byte[] rawData, ReaderOptions options = null) {
return false;
}
And I would like to have something like this:
#region overloadedReadFromMethods
/// <summary>
/// Description that described summary of an overloaded method.
/// </summary>
/// <param name="fileName">Description that describes filename parameter</param>
/// <param name="options">Description that describes options parameter</param>
/// <returns>Description of what method returns</returns>
public bool ReadFrom(string fileName, ReaderOptions options = null) {
return false;
}
/// <param name="stream">Description that describes stream parameter</param>
public bool ReadFrom(Stream stream, ReaderOptions options = null) {
return false;
}
/// <param name="rawData">Description that describes rawData parameter</param>
/// <returns>Even considering that returns tag is present on the first overloaded method,
/// this overloaded method shows this specific description.
/// </returns>
public bool ReadFrom(byte[] rawData, ReaderOptions options = null) {
return false;
}
#endregion overloadedReadFromMethods
So the first overloaded method describes default description and then methods below can override it with their own descriptions. I want it to show in Visual Studio's IntelliSense.

TLDR - It's not possible
Long story short, as was the case in the past, you still cannot re-use comments this way.
Some interesting ideas here
Create one function with optional parameters. While this would mitigate the problem, I find that optional parameters are sometimes incovenient themselves as they overcomplicate the logic inside and make unit testing very difficult. Overaloading in your case make sense, so this solution does not apply.
Use the <overloads> comment. I can't see it in the official documentation though
Use the <see> and <seealso> xml tag to use reference
Use the <include> tag
This is still not a solution but it allows you to have separate xml documents and handle overall. include documentation

I think the extra work to document each method is necessary because they all have different signatures. Methods have different <param></param>
InheritDoc is a package that can be used to inherit xml docs.

Related

How can I test that LINQ Range operator is deferred?

I have implemented some sort of LINQ Range operator and do want to have a test which will verify that the Range operator is actually deferred.
My Range operator methods:
/// <summary>
/// The Range static method, validation part.
/// </summary>
/// <param name="start">The start.</param>
/// <param name="count">The count.</param>
/// <returns></returns>
public static IEnumerable<int> Range(int start, int count)
{
long max = ((long) start) + count - 1;
if (count < 0 || max > Int32.MaxValue) throw new ArgumentOutOfRangeException(nameof(count));
return RangeIterator(start, count);
}
/// <summary>
/// The Range operator iterator.
/// </summary>
/// <param name="start">The start.</param>
/// <param name="count">The count.</param>
/// <returns></returns>
static IEnumerable<int> RangeIterator(int start, int count)
{
for (int i = 0; i < count; ++i)
{
yield return start + i;
}
}
For the other deferred operators I have created ThrowingExceptionEnumerable utility class, which helps with testing:
/// <summary>
/// The class responsible for verifying that linq operator is deferred.
/// </summary>
/// <typeparam name="T"></typeparam>
public sealed class ThrowingExceptionEnumerable<T> : IEnumerable<T>
{
/// <summary>
/// The methods throws <see cref="InvalidOperationException"/>.
/// </summary>
/// <returns></returns>
public IEnumerator<T> GetEnumerator()
{
throw new InvalidOperationException();
}
/// <inheritdoc />
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
/// <summary>
/// The method which checks that the given <see cref="deferredFunction"/> actually uses deferred execution.
/// When the function just call itself it should not throw an exception. But, when using the result
/// by calling <see cref="GetEnumerator"/> and than GetNext() methods should throws the <see cref="InvalidOperationException"/>.
/// </summary>
/// <typeparam name="TSource">The deferred function source type.</typeparam>
/// <typeparam name="TResult">The deferred function result type.</typeparam>
/// <param name="deferredFunction">The deferred function (unit of work under the test).</param>
public static void AssertDeferred<TSource,TResult>(
Func<IEnumerable<TSource>, IEnumerable<TResult>> deferredFunction)
{
var source = new ThrowingExceptionEnumerable<TSource>();
// Does not throw any exception here, because GetEnumerator() method is not yet used.
var result = deferredFunction(source);
// Does not throw InvalidOperationException even here, despite the fact that we retrieve the enumerator.
using var iterator = result.GetEnumerator();
Assert.Throws<InvalidOperationException>(() => iterator.MoveNext());
}
And for instance deferred Select operator has the following test:
/// <summary>
/// Should check that Select operator is deferred.
/// </summary>
[Fact]
public void VerifySelectExecutionIsDeferred()
{
ThrowingExceptionEnumerable<int>.AssertDeferred<int, int>(source => source.Select(x => x));
}
The first problem I have faced during writing such unit test for the Range operator is that Range is actually a static method and not an extension method. Also the thing is, that Range signature does not have a source parameter, so the same approach can not be used.
Do you have some clever ideas, how it can be tested?
External code isn't going to be able to do anything to verify that the values are generated on the fly. The only actual difference between a method like this and one that materializes a collection and returns it is the memory footprint at scale, which is quite difficult to reliably test in a unit test.
You can clearly tell that it doesn't do that my looking at the code, but you'd need to alter the implementation in some pretty significant way to end up with something that would allow you to verify that in a unit test (such as writing a more generalized "Generate" method that used a delegate to generate the next value).
If you had some sort of hard requirement that your implementation has unit tests to verify such things, I'd write such a Generate method, implement your Range method by calling Generate, write a unit test to verify that Generate doesn't call the delegate until generating the next value in the sequence, and then assert that the Range method defers execution because it uses Generate to produce its sequence. I wouldn't want to do this in production code though, this would really be just a way of meeting the requirement and making some sacrifices in readability and (mild) performance for the sake of it.

How to reference type parameter in XML documentation?

How do you reference a type parameter in XML code documentation? For instance, this code
/// <summary>
/// An interface.
/// </summary>
/// <typeparam name="TInterface">Type paramter.</typeparam>
public interface IFace<TInterface>
{
/// <summary>
/// Does the thing.
/// </summary>
/// <typeparam name="TMethod">Different from <see cref="TInterface"/>.</typeparam>
/// <returns>An integer.</returns>
int SomeMethod<TMethod>();
}
Gives a warning about typeparam name="TMethod":
XML comment has cref attribute 'TInterface' that refers to a type paramter.
This question asks about referencing a generic type, but I want to reference the type parameter.
Instead of using see cref, the typeparamref should be used instead:
/// <summary>
/// An interface.
/// </summary>
/// <typeparam name="TInterface">Type paramter.</typeparam>
public interface IFace<TInterface>
{
/// <summary>
/// Does the thing.
/// </summary>
/// <typeparam name="TMethod">Different from <typeparamref name="TInterface"/>.</typeparam>
/// <returns>An integer.</returns>
int SomeMethod<TMethod>();
}

StyleCop SA1620, I don't know how to resolve my XML Comments to its liking

I have the following code w/comments: (It does compile)
/// <summary>
/// return a passing result of a particular type
/// </summary>
/// <typeparam name="T">Type of the value to be returned</typeparam>
/// <param name="value">the value to be returned</param>
/// <returns>a passing result</returns>
public static Result<T> Pass(T value)
{
return new Result<T>()
{
Passed = true,
Value = value
};
}
I get the following warning with it:
Warning 1 SA1620 : CSharp.Documentation :
The typeparam tags in the documentation header must
match the generic types for the method.
I did look at the help page for this error, which gives this explanation:
To fix a violation of this rule, add and fill-in one tag
for each generic type parameter on the element, and make sure that
the tags appear in the same order as the element’s type
parameters.
And it has provided sample code:
/// <summary>
/// A sample generic class.
/// </summary>
/// <typeparam name="S">The first generic type parameter.</typeparam>
/// <typeparam name="T">The second generic type parameter.</typeparam>
public class Class1<S, T>
{
}
I don't see anything about mine that breaks the standards it is showing, and I have tried various odd things, but I have no real idea of what I'm supposed to do here.
The only way that this can compile is if this method is inside a class that is generic in T. This method doesn't have any type parameters. If it was generic, there would be type parameters after the name of the method:
public static Result<T> Pass<T>(T value)
{
return new Result<T>()
{
Passed = true,
Value = value
};
}
But that's not the case with your method. So it must be:
class SomeClass<T>
{
public static Result<T> Pass(T value)
{
return new Result<T>()
{
Passed = true,
Value = value
};
}
}
And any documentation about the type parameter belongs up at the class level. E.g.:
/// <summary>
/// This is a result class
/// </summary>
/// <typeparam name="T">Type of the value to be returned</typeparam>
public class Result<T>
{
public bool Passed { get; set; }
public T Value { get; set; }
/// <summary>
/// return a passing result of a particular type
/// </summary>
/// <param name="value">the value to be returned</param>
/// <returns>a passing result</returns>
public static Result<T> Pass(T value)
{
return new Result<T>()
{
Passed = true,
Value = value
};
}
}

Moles and AppSettingsReader?

I'm working with Moles to write some unit tests. I searched online but I don't see any responses on how to use Moles to intercept the calls to AppSettingsReader.GetValue.
Has anyone been able to do this using Moles? Or am I forced into isolating the calls in my own class I can inject or mock? Ideally there is a way to directly use Moles to intercept the calls because we don't really want to modify the code we're looking to put under test.
Thanks!
Firstly, I strongly recommend moving to the release version of Moles, called "Fakes and Stubs", in .NET 4.5 / C# 5 / Visual Studio 2012.
The System.Configurations namespace is incompatible with the Mole/Fake type, and must be stubbed. To create a stub using the Moles Framework, simply create an interface for the System.Configuration.AppSettingsReader type. The Moles compiler will automatically convert the interface into a Stub type.
Here's an interface you can add to your project:
using System;
namespace YOUR_NAMESPACE_HERE
{
/// <summary>
/// IOC object for stubbing System.Configuration.AppSettingsReader.
/// Provides a method for reading values of a particular type from
/// the configuration.
/// </summary>
interface IAppSettingsReader
{
/// <summary>
/// Gets the value for a specified key from the
/// System.Configuration.ConfigurationSettings.AppSettings property
/// and returns an object of the specified type containing the
/// value from the configuration.
/// </summary>
/// <param name="key">The key for which to get the value.</param>
/// <param name="type">The type of the object to return.</param>
/// <returns>The value of the specified key</returns>
/// <exception cref="System.ArgumentNullException">key is null.
/// - or -
/// type is null.</exception>
/// <exception cref="System.InvalidOperationException">key does
/// not exist in the <appSettings> configuration section.
/// - or -
/// The value in the <appSettings> configuration section
/// for key is not of type type.</exception>
public object GetValue(string key, Type type);
}
}
Here's a stub class, too:
using System;
using System.Configuration;
namespace YOUR_NAMESPACE_HERE
{
/// <summary>
/// Production stub for System.Configuration.AppSettingsReader.
/// Provides a method for reading values of a particular type from
/// the configuration.
/// </summary>
public class AppSettingsReaderStub : IAppSettingsReader
{
/// <summary>
/// Gets the value for a specified key from the
/// System.Configuration.ConfigurationSettings.AppSettings property
/// and returns an object of the specified type containing the value
/// from the configuration.
/// </summary>
/// <param name="key">The key for which to get the value.</param>
/// <param name="type">The type of the object to return.</param>
/// <returns>The value of the specified key</returns>
/// <exception cref="System.ArgumentNullException">key is null.
/// - or -
/// type is null.</exception>
/// <exception cref="System.InvalidOperationException">key does not
/// exist in the <appSettings> configuration section.
/// - or -
/// The value in the <appSettings> configuration section for
/// key is not of type type.</exception>
public object GetValue(string key, Type type)
{
var reader = new AppSettingsReader();
object result = reader.GetValue(key, type);
return result;
}
}
}

Is there a C# equivalent of typeof for properties/methods/members?

A classes Type metadata can be obtained in several ways. Two of them are:
var typeInfo = Type.GetType("MyClass")
and
var typeInfo = typeof(MyClass)
The advantage of the second way is that typos will be caught by the compiler, and the IDE can understand what I'm talking about (allowing features like refactoring to work without silently breaking the code)
Does there exist an equivalent way of strongly referencing members/properties/methods for metadata and reflection? Can I replace:
var propertyInfo = typeof(MyClass).GetProperty("MyProperty")
with something like:
var propertyInfo = property(MyClass.MyProperty)
No, unfortunately not. It's been discussed and even named: infoof (pronounced "in-foof" for comedy value) but it's not been implemented... yet. Eric Lippert has a blog post about it.
The closest you can come in C# 3 is to make the compiler generate an expression tree, and then pull it out of that - but that's hardly pleasant.
I've just implemented an equivalent of constructions 'propertyof' 'methodof' 'fieldof' using Syste.Linq.Expressions
so instead of writing
var mi = typeof (string).GetMethod("Concat", new[] {typeof (object), typeof (object)});
you can use:
var mi = ReflectionHelper.MethodOf(() => string.Concat(new object(), new object()));
Why do we need this? because now we safe to refactor method, we use via reflection
listing of helper class (you may need to add some informative exceptions in methods):
/// <summary>
/// Represents a set of helpers for .net reflection
/// </summary>
public static class ReflectionHelper
{
#region Public methods
/// <summary>
/// Gets a MethodInfo object from specified expression
/// </summary>
/// <typeparam name="TResult"></typeparam>
/// <param name="methodExpression"></param>
/// <returns></returns>
public static MethodInfo MethodOf<TResult>(Expression<Func<TResult>> methodExpression)
{
return ((MethodCallExpression)methodExpression.Body).Method;
}
/// <summary>
/// Gets a MethodInfo object from specified expression
/// </summary>
/// <param name="methodExpression"></param>
/// <returns></returns>
public static MethodInfo MethodOf(Expression<Action> methodExpression)
{
return ((MethodCallExpression)methodExpression.Body).Method;
}
/// <summary>
/// Gets a MethodInfo object from specified expression
/// </summary>
/// <param name="methodExpression"></param>
/// <returns></returns>
public static MethodInfo MethodOf<TInstance, TResult>(Expression<Func<TInstance, TResult>> methodExpression)
{
return ((MethodCallExpression)methodExpression.Body).Method;
}
/// <summary>
/// Gets a MethodInfo object from specified expression
/// </summary>
/// <param name="methodExpression"></param>
/// <returns></returns>
public static MethodInfo MethodOf<TInstance>(Expression<Action<TInstance>> methodExpression)
{
return ((MethodCallExpression)methodExpression.Body).Method;
}
/// <summary>
/// Gets a PropertyInfo object from specified expression
/// </summary>
/// <param name="propertyGetExpression"></param>
/// <returns></returns>
public static PropertyInfo PropertyOf<TProperty>(Expression<Func<TProperty>> propertyGetExpression)
{
return ((MemberExpression)propertyGetExpression.Body).Member as PropertyInfo;
}
/// <summary>
/// Gets a PropertyInfo object from specified expression
/// </summary>
/// <param name="propertyGetExpression"></param>
/// <returns></returns>
public static PropertyInfo PropertyOf<TInstance, TProperty>(Expression<Func<TInstance, TProperty>> propertyGetExpression)
{
return ((MemberExpression)propertyGetExpression.Body).Member as PropertyInfo;
}
/// <summary>
/// Gets a FieldInfo object from specified expression
/// </summary>
/// <param name="fieldAccessExpression"></param>
/// <returns></returns>
public static FieldInfo FieldsOf<TProperty>(Expression<Func<TProperty>> fieldAccessExpression)
{
return ((MemberExpression)fieldAccessExpression.Body).Member as FieldInfo;
}
//TODO: ConstructorOf(...)
#endregion //Public methods
}
as I understand we could not use same aproach to getParameterInfo or EventInfo
Another approach to do that, described by Jb Evain, see: http://evain.net/blog/articles/2010/05/05/parameterof-propertyof-methodof?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+jbevain+%28Jb+in+a+nutshell%29
In c# 6 there's still no infoof but there is nameof:
var propertyInfo = typeof(MyClass).GetProperty(nameof(MyClass.MyProperty))
It's certainly not more terse, but at least it's refactoring friendly.
No, there is no such syntax in c#.

Categories