0

I'm writing more library code and came across an annoyance - here is an example

public static TParam RequiredParam<TParam>(TParam param, string name) where TParam : class 
{
  return param ?? throw new ArgumentNullException(name);
}

private readonly int _testInt;

public TestClass(int testInt)
{
  _testInt = RequiredParam(testInt, nameof(testInt));
}

Basically I have to pass in the name in the usage

What I want to have is:

public static TParam RequiredParam<TParam>(TParam param) where TParam : class 
{
  return param ?? throw new ArgumentNullException(*NAME STILL GETS HERE SOMEHOW*);
}

private readonly int _testInt;

public TestClass(int testInt)
{
  _testInt = RequiredParam(testInt);
}

Is there a better way? Back in the days of WPF I used to use [CallerMemberName] like so:

private void PropertyChanged([CallerMemberName]string name = default)
{
  PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}

Does anyone know something similar to achieve the same result for this? Considering how often this library is called I don't mind stepping into post-build steps or whatever, but would prefer to avoid reflection for performance reasons.

Edit - Made my objective clearer

Xsjado
  • 347
  • 1
  • 10
  • To be honest with you, I didn't quite get what you want to achieve. – SᴇM Jun 21 '18 at 06:07
  • This means you'll have a different method to check reference types vs value types. I think you should use the same for readability reasons. – vc 74 Jun 21 '18 at 06:21
  • @SeM - I want to change the call from - RequiredParam(testInt, nameof(testInt)); - to - RequiredParam(testInt); But still log the name of the variable in the exception – Xsjado Jun 21 '18 at 06:42
  • @Xsjado if you could do this, we wouldn't have to use `nameof` in the first place, which mind you is only a later addition to C# – TheGeneral Jun 21 '18 at 06:47
  • @TheGeneral I know this, but I've seen other libraries do wonderful things with postbuild, it's both a nicer looking solution and a good segway to learning these techniques. – Xsjado Jun 21 '18 at 06:50
  • 1
    You could - well somehow - with an expression RequiredParam( () => testInt ) - read https://stackoverflow.com/questions/9801624/get-name-of-a-variable-or-parameter – Sir Rufo Jun 21 '18 at 06:51
  • @SirRufo - I considered something similar, by taking advantage of the named values now in tuples, but I don't think there are single value tuples :( – Xsjado Jun 21 '18 at 06:52

1 Answers1

1

Firstly, i personally wouldn't do that anyway, you are hiding logic behind another method to save a couple of keystrokes. In doing this, for new readers they will have to click through to see what it does, and you still have to use nameof anyway.

You could probably do something with reflection, but even then it will be a lot of work for dubious gain.

Can i suggest a 3rd approach?

Why don't you just create a Resharper template for the keywords args[tab]

$NAME$ = $NAME$ ?? throw new ArgumentNullException(nameof($NAME$));

The benefits are

  • New readers can easily see whats going on.
  • You only have minimal key strokes as it will suggest the type after a few letters
  • You save a bit of IL and a call to the stack

Also if you use Resharper, check out Code Annotation Attributes


You could also use an expression i guess

Example

public void ExampleFunction(Expression<Func<string, string>> f) {
    Console.WriteLine((f.Body as MemberExpression).Member.Name);
}

Usage

ExampleFunction(x => WhatIsMyName);

Still in my opinion, nothing is really gained

TheGeneral
  • 79,002
  • 9
  • 103
  • 141