Reputation: 21
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.
Upvotes: 1
Views: 2751
Reputation: 225
If you're running C# 10/.NET 5 or later, you can simply prepend [CallerArgumentExpression(nameof(@object))]
to your stringKey
argument to get what you want. You can then remove your IsNullOrEmpty()
check, and also the caller doesn't have to supply a third parameter:
using System.Runtime.CompilerServices;
// ...
public static bool GetValue<T>(Dictionary<string, object> dict, ref T @object,
[CallerArgumentExpression(nameof(@object))] string stringKey = "")
{
dict.TryGetValue(stringKey, out var Object);
// ...
}
Upvotes: 0
Reputation: 16453
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.
Upvotes: 1
Reputation: 15227
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.
Upvotes: 2
Reputation: 77364
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.
Upvotes: 4