Add completion suggestion 'nameof' for parameter with Resharper - c#

I would like to add a completion suggestion of nameof to a parameter in a method.
The method:
public static class Ensure
{
/// <summary>
/// throws <see cref="ArgumentException"/> exception if string is null or empty.
/// </summary>
/// <param name="value">string to check its content.</param>
/// <param name="name">name of parameter passed.</param>
public static void StringNotNullOrEmpty(string value, string name)
{
if (string.IsNullOrEmpty(value))
{
throw new ArgumentException("Value cannot be null or empty", name);
}
}
}
When typing Ensure.StringNotNullOrEmpty(testString, <...>) I would like to get the nameof(testString) suggestion for <...>. The above method doesn't suggest the nameof (Worse still, after typing 'n' I only get suggestions as null, new). The nameof(...) is necessary so I get the correct ParamName in the ArgumentException.
On the site of Resharper it says that ArgumentNullException makes use of the nameof suggestion by using the InvokerParameterNameAttribute (source: Resharper InvokerParameterNameAttribute).
Attempt:
So I installed the nuget package in my project: JetBrains.Annotations 10.4.0 and changed the method as followed:
public static class Ensure
{
/// <summary>
/// throws <see cref="ArgumentException"/> exception if string is null or empty.
/// </summary>
/// <param name="value">string to check its content.</param>
/// <param name="name">name of parameter passed.</param>
public static void StringNotNullOrEmpty([CanBeNull] string value,
[NotNull] [InvokerParameterName] string name)
{
if (string.IsNullOrEmpty(value))
{
throw new ArgumentException("Value cannot be null or empty", name);
}
}
}
Unfortunately the above attempt is still not giving me the suggestion of nameof when I've typed: Ensure.StringIsNotNullOrEmpty(testString,.
Some other thing I found was the CallerMemberNameAttribute on MSDN. But this only gives me the name of the calling method as a string.
I also looked into some repo's on GitHub, and could only find solutions the same way as my attempt.
One reason I can think of is when having two string parameters in a method with an InvokerParameterNameAttribute defined on the latter, it could be confusing for Resharper.
Is it possible to add the nameof suggestion for a parameter in a method? And how can I achieve this with the above method?
Additional info:
I have VS2015 + Resharper 2016.3.2.

actually that works (but not as you intended). it will not suggest as soon as you type ,... it will only suggest you to use nameof expression when you fully type name of argument in form of string instead of using nameof expression.
static void Caller(string arg)
{
StringNotNullOrEmpty(arg, "arg"); // only now resharper suggests to use nameof.
StringNotNullOrEmpty(arg, "something else"); // now resharper complains about unknown argument name.
}
You can submit feedback on resharper to actually implement the behavior you want.
Also if you type "" the cursor will move to middle of double quotes and resharper suggests name of available parameters.
BTW you can always comment your code that can be useful for every future readers
/// <summary>
/// throws <see cref="ArgumentException"/> exception if string is null or empty.
/// </summary>
/// <param name="value">string to check its content.</param>
/// <param name="name">name of parameter passed.</param>
public static void StringNotNullOrEmpty([CanBeNull] string value,
[NotNull] [InvokerParameterName] string name)
{
if (string.IsNullOrEmpty(value))
{
throw new ArgumentException("Value cannot be null or empty", name);
}
}

Related

Null Guard for Nested Objects With Hierarchy Path Recognition in C#

I'm trying to create a nested Guard method (or find an existing Guard library) that would throw an exception if any object in a nested hierarchy is NULL and include the name of the object hierarchy path up to and including NULL. I also want to avoid fluent API syntax of checking each object. Please assume example below.
Assume the following hierarchy:
Country.State.City.Person
Example of usage I'm trying to achieve:
Guard.ThrowIfNull(Country.State.City.Person);
or
Guard.ThrowIfNull(() => Country.State.City.Person);
EXPECTED RESULT:
if Person is NULL, then throw ArgumentNullException("Country.State.City.Person")
if City is NULL, then throw ArgumentNullException("Country.State.City")
if State is NULL, then throw ArgumentNullException("Country.State")
if Country is NULL, then throw ArgumentNullException("Country")
At minimum, I believe you'll need to pass an instance to the Guard.ThrowIfNull function in addition to the path you want to check.
I wrote a proof of concept below that exhibits the behavior you describe. It does not handle collections, however. (In the case that State is a collection, this code will fail for "Country.State.City".)
Usage:
Guard.ThrowIfNull(country, "Country.State.City.Person");
// Or
Guard.ThrowIfNull(country, x => x.State.City.Person);
Code:
public static class Guard
{
/// <summary>
/// Throws an ArgumentNullException if any portion of a given property path is null.
/// </summary>
/// <typeparam name="T">The type to check.</typeparam>
/// <param name="instanceToCheck">The instance to check</param>
/// <param name="pathToCheck">The full path of the property to check. The path should include the name of the instance type.</param>
public static void ThrowIfNull<T>(T instanceToCheck, string pathToCheck)
{
var propsToCheck = pathToCheck?.Split('.');
if (propsToCheck?.Any() != true)
{
throw new ArgumentNullException(nameof(pathToCheck));
}
if (typeof(T).Name != propsToCheck.First())
{
throw new ArgumentException($"The type of {nameof(instanceToCheck)} does not match the given {nameof(pathToCheck)}.");
}
if (instanceToCheck == null)
{
throw new ArgumentNullException($"{pathToCheck.First()}");
}
object currentObj = instanceToCheck;
for (var i = 1; i < propsToCheck.Length; i++)
{
var prop = currentObj.GetType().GetProperties().FirstOrDefault(x => x.Name == propsToCheck[i]);
if (prop == null)
{
throw new ArgumentException($"The path, '{string.Join(".", propsToCheck.Take(i + 1))}' could not be found.");
}
currentObj = prop.GetValue(currentObj);
if (currentObj == null)
{
throw new ArgumentNullException($"{string.Join(".", propsToCheck.Take(i + 1))}");
}
}
}
/// <summary>
/// Throws an ArgumentNullException if any portion of a given property path is null.
/// </summary>
/// <typeparam name="T">The type to check.</typeparam>
/// <param name="instanceToCheck">The instance to check</param>
/// <param name="pathToCheck">The full path of the property to check.</param>
public static void ThrowIfNull<T, TProp>(T instanceToCheck, Expression<Func<T, TProp>> pathToCheck)
{
ThrowIfNull(instanceToCheck, (typeof(T).Name + pathToCheck.ToString().Substring(pathToCheck.ToString().IndexOf("."))));
}
}

InvalidCastException while casting to defined Type C#

I have a Dictionary containing strings as keys, and objects as values in an abstract class.
I have two classes deriving from this abstract class.
One of the deriving classes works perfectly, all configurations and items are loaded and retrievable without issues.
However, the other class is giving me headaches.
When I try to get an object of type "Domain"; I get an invalid cast exception, although I am adding the value to the dictionary as said type.
Here is the code:
public sealed class UserDomainConfig: ConfigParser {
public UserDomainConfig(string configFilePath) : base(configFilePath) { }
public Domain GetConfig(string key) => GetConfig<Domain>(key);
public override bool LoadConfigs() {
return base.LoadConfigs();
}
public UserDomainConfig SetConfig(string key, Domain value) {
base.SetConfig(key, value);
return this;
}
}
public abstract class ConfigParser: IConfig {
/* Snip */
/// <summary>
/// Gets the config.
/// </summary>
/// <returns>The config.</returns>
/// <param name="key">Key.</param>
/// <typeparam name="T">The 1st type parameter.</typeparam>
public virtual T GetConfig<T>(string key) {
object output = null;
try {
if (!configs.TryGetValue(key, out output))
return default(T);
//return (T)output;
//return output as T;
// This is where the exception is occurring.
// I've tried multiple solutions to try to remedy this issue.
return (T)Convert.ChangeType(output, typeof(T));
} catch (InvalidCastException ex) {
logger.Error($"Failed to cast config { key }!");
}
return default(T);
}
/// <summary>
/// Sets the config.
/// </summary>
/// <returns>The config.</returns>
/// <param name="key">Key.</param>
/// <param name="value">Value.</param>
/// <typeparam name="T">The 1st type parameter.</typeparam>
public virtual IConfig SetConfig<T>(string key, T value) {
if (KeyExists(key))
configs.Remove(key);
configs.Add(key, value);
return this;
}
Any ideas on how to fix this, and/or why this isn't working in the first place, although it works like a charm with strings, bools, and ints?
The Convert class only supports simple types, known by .NET, like Int32, String, DateTime. It does not support user defined or complex types like Domain. If you try to convert something to a not-supported type, the method Convert.ChangeType throws an InvalidCastException. The only exception is that it will work if the Original value (output) is already of that desired type; than no actual conversion is needed.
For more information, read: https://msdn.microsoft.com/en-us/library/dtb69x08(v=vs.110).aspx
If you are certain the stored value is of the type Domain, than log more information. Something like this:
logger.Error($"Failed to cast config { key } of type { output.GetType() } to type { typeof(T) }!");
This way you can verify your claim that both types are the same.

Using nameof to get name of current method

Have browsed, searched and hoped but cannot find a straight answer.
Is there anyway in C# 6.0 to get the current method name using nameof withouth specifying the method name?
I am adding my test results to a dictionary like this:
Results.Add(nameof(Process_AddingTwoConsents_ThreeExpectedRowsAreWrittenToStream), result);
I would prefer if I would not have to specify the method name explicitly so I can copy+paste the line, a non-working example:
Results.Add(nameof(this.GetExecutingMethod()), result);
If possible I do not want to use Reflection.
UPDATE
This is not (as suggested) a duplicate of this question. I am asking if is explicitly possible to make use of nameof without(!) reflection to get the current method name.
You can't use nameof to achieve that, but how about this workaround:
The below uses no direct reflection (just like nameof) and no explicit method name.
Results.Add(GetCaller(), result);
public static string GetCaller([CallerMemberName] string caller = null)
{
return caller;
}
GetCaller returns the name of any method that calls it.
Building on user3185569's great answer:
public static string GetMethodName(this object type, [CallerMemberName] string caller = null)
{
return type.GetType().FullName + "." + caller;
}
Results in you being able to call this.GetMethodName() anywhere to return the fully qualified method name.
Same as others, but some variation:
/// <summary>
/// Returns the caller method name.
/// </summary>
/// <param name="type"></param>
/// <param name="caller"></param>
/// <param name="fullName">if true returns the fully qualified name of the type, including its namespace but not its assembly.</param>
/// <returns></returns>
public static string GetMethodName(this object type, [CallerMemberName] string caller = null, bool fullName = false)
{
if (type == null) throw new ArgumentNullException(nameof(type));
var name = fullName ? type.GetType().FullName : type.GetType().Name;
return $"{name}.{caller}()";
}
Allows to call it like this:
Log.Debug($"Enter {this.GetMethodName()}...");
If you want to add the name of the current method into the Results List then you may use this :
StackTrace sTrace= new StackTrace();
StackFrame sFrame= sTrace.GetFrame(0);
MethodBase currentMethodName = sFrame.GetMethod();
Results.Add(currentMethodName.Name, result);
Or you can use,
Results.Add(new StackTrace().GetFrame(0).GetMethod().Name, result);

Override [NotNull] Attribute correctly

I inherit from ArrayList and override the Add method (see below).
It's curious that the Add() method has marked the object value parameter as [NotNull] and the documentation says "This value can be a null reference".
Anyway I've marked it now as [CanBeNull] (via a ReSharper annotation attribute).
But IntelliSense still gives me the cached documentation that marks the parameter as [NotNull].
Why isn't the documentation overridden?
/// <summary>
/// Bla bla
/// </summary>
/// <param name="value">
/// This Attribute is marked as CanBeNull.
/// </param>
/// <returns></returns>
public override int Add([CanBeNull] object value)
{
if (value != null)
{
// Do sth.
}
}
Although overridden [NotNull] attributes with [CanBeNull] are respected by ReSharper's nullability analysis and are also shown in the Ctrl+Shift+F1 window, ReSharper incorrectly ignores them in the parameter info.
I created RSRP-447900.

How do you provide xml comments/documentation for delegate parameters?

given a delegate like
Func<string,string,string> MyFunc = (firstName,lastName) => string.Format("Given Name:{0} Surname:{1}",
firstName,
lastName);
How would you can you document the parameters of firstName and lastName, so they show up in intellisense (like method descriptions and parameters do)?
Example:
/// <summary>
/// My Method
/// </summary>
/// <param name="firstName">The first name.</param>
/// <param name="lastName">The last name.</param>
/// <returns></returns>
public string MyMethod(string firstName, string lastName)
{
return string.Format("Given Name:{0} Surname:{1}",firstName,lastName);
}
I want to hover over the delegate or have intellisense popup when I type and tell me the descriptions for the the delegate parameters, like it would with the above method.
A field of a delegate type is still a field and not a method—it doesn't take parameters in itself. The parameters belong to the delegate type, not the delegate field. You can write the comments for parameters when you delegate types if you want.
/// <summary>
/// Tests something.
/// </summary>
/// <param name="test">Something that's going to be tested.</param>
delegate void Test(int test);
Func<string,string,string> is a general delegate for functions with three parameters. For specific purposes, you can always declare your own delegate type that represents the abstracted method more specifically and add comments to its parameters.

Categories