2

In C#, I am defining a static field of a specific class. From within the class, I want to be able to display the name of the static field, pretty much like this:

public class Unit {
  public string NameOfField { get { return ...; } }
}

public static Unit Hectare = new Unit();

If I now access:

Hectare.NameOfField

I want it to return:

Hectare

I know there is a static function System.Reflection.MethodBase.GetCurrentMethod(), but as far as I can tell there is no way to get the name of the instance containing this current method?

There is also the System.RuntimeFieldHandle structure, but I have not been able to identify any GetCurrentFieldHandle() method.

I am not sure if I am missing something obvious?

Any help on this is very much appreciated.

Anders Gustafsson
  • 15,837
  • 8
  • 56
  • 114
  • 2
    There can be no way to do this from within the Unit class. What if more than one variable refers to the same instance? – Blorgbeard Apr 05 '11 at 09:15
  • Can't you just pass the name to the constructor and store it in a field in Unit? `public static Unit Hectare = new Unit("Hectare");` – Henrik Apr 05 '11 at 09:17
  • 2
    You seem to be asking for the name of the runtime variable that your class instance is assigned to. You can't do this with c# – IanNorton Apr 05 '11 at 09:22
  • Thanks for your comments, Blorgbeard, Henrik and Ian. It all makes sense :-) I might need to do it the way you Henrik (as well as @Gerrie and @Manji) suggest. I have hoped to avoid the extra typing, but that's life... – Anders Gustafsson Apr 05 '11 at 10:08

4 Answers4

1

You should not count on variable names in you developments as they do not exits at runtime.

It's better to initialize Unit with a name directly:

public class Unit {

  public Unit(string name)
  {
     NameOfField = name;
  }
  public string NameOfField { get; private set;} }
}

public static Unit Hectare = new Unit("Hectare");
manji
  • 47,442
  • 5
  • 96
  • 103
  • Thanks for the answer Manji. I have thought about this, but I have quite a lot of static fields and I want to avoid the required refactoring. But I might have to reconsider... – Anders Gustafsson Apr 05 '11 at 09:52
  • it's better yes. May be you can use a regexp to do a massive seach/replace with vsiual studio: search for `public[ ]+static[ ]+Unit[ ]+{[^ ]+}[ ]+=[ ]+new[ ]+Unit\(\)` and replace it by `public static Unit \1 = new Unit("\1")` – manji Apr 05 '11 at 10:07
  • It is great that you are providing the regex, it usually takes me a big part of the day when I am trying to compose regexes myself :-) As you can see below I have implemented a solution to my specific problem, so luckily I do not need to do the refactoring. Thanks anyway for your efforts. – Anders Gustafsson Apr 05 '11 at 20:21
0

Only way around this will be to store that information in the class:

public static Unit Hectare = new Unit("Hectare");

When your code is compiled all variable names are lost and replaced by internal references. There is no way to get that name again.

Gerrie Schenck
  • 22,148
  • 20
  • 68
  • 95
  • Thanks for the answer Gerrie. As I also mention in the answer to Manji above, I have quite a lot of static fields and I want to avoid the required refactoring. But if there is no other way out... – Anders Gustafsson Apr 05 '11 at 09:54
0

You can use Reflection to obtain class Fields and properties. Like below:

Suppose you have class with one property:

class Test
{
    public static string MySupperField
    {
        get
        {
            return "Some symbols here";
        }
    }
}

......

You can read the property name in such way:

public string[] GetClassStaticNames(Type T)
{
    string[] names;

    System.Reflection.PropertyInfo[] props = T.GetProperties(); // This will return only properties not fields! For fields obtaining use T.GetFields();

    names = new string[props.Count()];
    for (int i = 0; i < props.Count(); i++)
    {
        names[i] = props[i].Name;
    }

    return names;
}

Hope this will help.

[EDIT]
Returning to your question - No you cant obtain name of current variable.
What you are asking about cant be done because of classes nature, they are objects in memory and reference to one object can be held in many variables, and when you are requesting value of instance field or property it will be actually performed operation with object in memory not with variable wich holds reference to that object. So obtaining name of variable wich holds reference to current instance have no sence

Anton Semenov
  • 6,227
  • 5
  • 41
  • 69
  • I have thought about getting the field names from the containing class. In principle I should be able to match the current field with the list of field in the containing class. I was hoping for a quicker way, but all answers I have got are quite discouraging in this respect :-) Any way, many thanks for the answer, Anton. – Anders Gustafsson Apr 05 '11 at 10:01
  • Thanks again Anton. @Blorgbeard made a similar comment above. I see the point, the fact that the object can be held in many variables more or less disqualifies my request. I'll have to reconsider my implementation. Good to have it discussed, anyway. Thanks. – Anders Gustafsson Apr 05 '11 at 10:13
0

Thanks everyone who has taken the time to answer and discuss my question.

Just to let you know, I have implemented a solution that is sufficient for my needs. The solution is not general, and it has some pitfalls, but I'd thought I share it anyway in case it can be of help to someone else.

This is in principle what the class that is used when defining fields looks like:

public class Unit : IUnit {
  public NameOfField { get; set; }
  ...
}

As you can see, the class implements the IUnit interface, and I have provided a public setter in the NameOfField property.

The static fields are typically defined like this within some containing class:

public static Unit Hectare = new Unit();

My solution is to set the NameOfField property through reflection before the field is used in the implementation. I do this through a static constructor (that of course needs to be invoked before the Unit fields are accessed. I use Linq to traverse the executing assembly for the relevant fields, and when I have detected these fields (fields which type implements the IUnit interface), I set the NameOfField property for each of them using the Any extension method:

Assembly.GetExecutingAssembly().GetTypes().
  SelectMany(type => type.GetFields(BindingFlags.Public | BindingFlags.Static)).
  Where(fieldInfo => fieldInfo.FieldType.GetInterfaces().Contains(typeof(IUnit))).
  Any(fieldInfo =>
  {
    ((IUnit)fieldInfo.GetValue(null)).NameOfField= fieldInfo.Name;
    return false;
  });

There are some shortcomings with this approach:

  • The static constructor has to be invoked through manual intervention before any Unit fields can be accessed
  • The NameOfField setter is public. In my case this is no problem, but it might be when applied in other scenarios. (I assume that the setter could be made private and invoked through further reflection, but I have not taken the time to explore that path further.)
  • ... ?

Either way, maybe this solution can be of help to someone else than me.

Anders Gustafsson
  • 15,837
  • 8
  • 56
  • 114