KDecker
KDecker

Reputation: 7128

Printing the name of a variable with nameOf that references another variable?

I have multiple instances of a class that I would like to track within an array that holds this type of class that I do not control. To do so I have created a List<MyClass> that I then compare to each value in the MyClass[] that I do not control.

I then print out the name of the class references with the C#6.0 operator nameOf. To my surprise (well its obvious now why) when I go to print the name of the class references when checking it from the List the loop variable name is printed instead of the class reference it references.

Is there a way to print the name of a variable that is referenced by another variable?

(Also what is the proper jargon to use for this question, I feel like I butchered it?)


Here is an example of the issue using Control

Control x = new Control();
Control y = new Control();
Control z = new Control();
var controlArr = new Control[] { x, y, z };
var controlList = new List<Control>() { x, y, z };
for (int i = 0; i < controlArr.Length; i++)
{
    Control anArrControl = controlArr[i];
    foreach (var aListControl in controlList)
        if (anArrControl == aListControl)
            Console.Out.WriteLine("Control[" + i + "]: " + nameof(aListControl));
}

This code will print

Control[0]: aListControl 
Control[1]: aListControl 
Control[2]: aListControl 

Instead of

Control[0]: x
Control[1]: y
Control[2]: z

EDIT: This example is simple in that if the Control[] does not contain a reference in the List<Control> nothing will be printed. In my actual application I take care of this. I simply put the example code to demonstrate what I mean when I asked the question, I didn't feel as if I worded it properly.

Upvotes: 2

Views: 418

Answers (2)

Ralf B&#246;nning
Ralf B&#246;nning

Reputation: 15405

On MSDN you find a reference of use cases that motivated the creation of the nameof function. The name of a reference is not defined at compile time. Given

 var a = new object();
 var b = a;
 var array = new [] {a, b}

What should nameof(array[1]) return ? It is the same referenced object.

Therefore you have to think of another workaround to achieve your goal. Perhaps a Dictionary might help you. Like

Control x = new Control();
Control y = new Control();
Control z = new Control();
var references = new Dictionary<Control, string> {
    { x, "x" }, { y, "y" }, {z, "z"}
};
var controlArr = new Control[] { x, y, z };
var controlList = new List<Control>() { x, y, z };
for (int i = 0; i < controlArr.Length; i++)
{
    Control anArrControl = controlArr[i];
    foreach (var aListControl in controlList)
        if (anArrControl == aListControl)
            Console.Out.WriteLine("Control[" + i + "]: " + references[aListControl]);
}

Upvotes: 3

Heinzi
Heinzi

Reputation: 172200

Nope, that won't work, since controlList does not contain x, y and z - it contains the controls that x, y and z refered to at the time of assignment.

There are two alternatives that you might want to consider:

  1. Store the control and its variable name in a List<Tuple<Control, String>>:

    var controlList = new[] {
        Tuple.Create(x, nameof(x)),
        Tuple.Create(y, nameof(y)),
        Tuple.Create(z, nameof(z))
    }.ToList();
    

    Obviously, your comparison then needs to be changed to anArrControl == aListControl.Item1.

  2. Some classes (such as WinForm's Control) have a Name property. Maybe that name suits your purpose as well?

Upvotes: 2

Related Questions