1

I am searching for solution for my project, where I have a Dictionary<string, object> and a helper method witch is trying to get some specific value from this dictionary.

As you can see below, if I don't have a stringKey, I am trying to get that stringKey from the @object (now it will return "object"). Surely, I can do it in calling, but it looks too bad for me.

Is there any way to do that in this method?

public static bool GetValue<T>(Dictionary<string, object> dict, ref T @object, 
    string stringKey = "") 
{
    if (string.IsNullOrEmpty(stringKey))
    {
       stringKey = nameof(@object);
    }

    dict.TryGetValue(stringKey, out var Object);
    if (Object != null)
    {
        @object = (T)Object;
        return true;
    }

    return false;
}

Example of calling:

DPH.GetValue(dictParam, ref Browser);

Expectations in method is that stringKey will be "Browser", as it will be in this case:

DPH.GetValue(dictParam, ref Browser, nameof(Browser));

There are specific needs and we are not able to refactor that dictionary to our object or our class at this moment, calling with nameof() is possible, but not a solution.

dymanoid
  • 14,771
  • 4
  • 36
  • 64
  • Just to clarify, you want to find the name of the passed-in ref variable at runtime? – Martin Sep 23 '19 at 15:20
  • Are you looking for something like https://stackoverflow.com/a/57992320/1462295 ? – BurnsBA Sep 23 '19 at 15:28
  • *"Surely, I can do it in calling, but it looks too bad for me."* What is bad about it? It's at the moment you're calling the method that you know what value you want to specify for the key. Also, this line seems very problematic: `@object = (T)Object;`. Why not just specify the input dictionary as `Dictionary` to avoid a cast which might fail? – Rufus L Sep 23 '19 at 15:32
  • 2
    Also, just FYI, the typical naming pattern for a method that tries to get a value, returns a `bool` indicating success, and which sets an object to the value is `TryGetValue` – Rufus L Sep 23 '19 at 15:36
  • 5
    I highly recommend not using `Object` and `@object` as names. – juharr Sep 23 '19 at 15:36

3 Answers3

4

You can't.

Sorry. There are some nice workarounds, but they all include completely changing what you do right now. You cannot get the name of a variable that way.

The only thing remotely similar to what you want is System.Runtime.CompilerServices.CallerMemberName and that only works to get the name of the function that called your function.

nvoigt
  • 75,013
  • 26
  • 93
  • 142
2

This is not possible in C#.

By calling

DPH.GetValue(dictParam, ref Browser);

you are providing object references to the called method. Browser is a named variable in this case (or a property, or a class field), but behind this named variable there is a reference to an object.

Think of an object reference as of a number that describes the object location somewhere in the memory.

The GetValue method gets two these numbers (references) and can access the objects using these numbers (references).

The method doesn't get any variable names.

So you have to provide the name of the variable using the nameof(Browser) value as the third argument. Otherwise, it's not possible to get the name.

dymanoid
  • 14,771
  • 4
  • 36
  • 64
1

As others have already said, this doesn't appear possible to achieve because there is no way to obtain the name of the reference parameter from the caller.

The reason why it's not possible is because the variable name is not included in the compiled IL output.

Consider the following:

int Fred = 0;
string FredName = nameof(Fred);

This declares Fred and FredName. However, in IL this results in:

.maxstack 2
.locals init (
    [0] int32,
    [1] string
)

You will see that Fred and FredName are indeed declared but as arguments 0 and 1. The variable names are not stored in the IL.

Furthermore, the code for nameof(...) simply does this:

IL_0003: ldstr "Fred"
IL_0008: stloc.1

Load the hardcoded value "Fred" into local variable 1.

Sadly, given this circumstance it seems impossible that you will achieve what you want.

Martin
  • 16,093
  • 1
  • 29
  • 48
  • 1
    Maybe `Browser` is a field in the OP's example, then there *will* be a name. But there's no way of getting it though (without weird `Expression` magic). – dymanoid Sep 23 '19 at 16:32
  • Even if you had a PDB, which *does* include local variable names, you still cannot do it, because in a lot of cases it is optimized away. For example, the function may be inlined, the variable location may be in a register, it may be the same location as another variable from a different part of the function. It is simply not even correct to consider the reference to be an actual memory address that is possible to be interrogated. – Charlieface Mar 11 '21 at 22:00