C#:有没有办法访问当前字段的名称?

发布于 2024-10-30 18:32:02 字数 525 浏览 1 评论 0原文

在 C# 中,我定义特定类的静态字段。在类中,我希望能够显示静态字段的名称,非常像这样:

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

public static Unit Hectare = new Unit();

如果我现在访问:

Hectare.NameOfField

我希望它返回:

Hectare

我知道有一个静态函数 System.Reflection.MethodBase.GetCurrentMethod( ),但据我所知,没有办法获取包含当前方法的实例的名称?

还有 System.RuntimeFieldHandle 结构,但我无法识别任何 GetCurrentFieldHandle() 方法。

我不确定我是否遗漏了一些明显的东西?

非常感谢对此的任何帮助。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

活雷疯 2024-11-06 18:32:02

您不应在开发中依赖变量名称,因为它们不会在运行时退出。

最好直接用名称来初始化 Unit:

public class Unit {

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

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

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");
因为看清所以看轻 2024-11-06 18:32:02

解决这个问题的唯一方法是将这些信息存储在类中:

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

编译代码时,所有变量名称都会丢失并被内部引用替换。没有办法再次获得这个名字。

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.

旧城空念 2024-11-06 18:32:02

您可以使用反射来获取类字段和属性。如下所示:

假设您有一个具有一个属性的类:

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

......

您可以通过以下方式读取属性名称:

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;
}

希望这会有所帮助。

[编辑]
回到你的问题 - 不,你无法获取当前变量的名称。
由于类的性质,您所问的问题无法完成,它们是内存中的对象,对一个对象的引用可以保存在许多变量中,当您请求实例字段或属性的值时,它实际上会与对象中的对象执行操作内存不包含变量,该变量保存对该对象的引用。因此,获取包含对当前实例的引用的变量名称是没有意义的

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

短叹 2024-11-06 18:32:02

感谢所有花时间回答和讨论我的问题的人。

只是为了让您知道,我已经实施了一个足以满足我的需求的解决方案。该解决方案并不通用,并且存在一些陷阱,但我想无论如何我都会分享它,以防它对其他人有帮助。

原则上,定义字段时使用的类如下所示:

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

如您所见,该类实现了 IUnit 接口,并且我在 NameOfField 属性中提供了一个公共 setter。

静态字段通常在某些包含类中定义如下:

public static Unit Hectare = new Unit();

我的解决方案是在实现中使用该字段之前通过反射设置 NameOfField 属性。
我通过静态构造函数来完成此操作(当然需要在访问 Unit 字段之前调用该构造函数。
我使用 Linq 遍历相关字段的执行程序集,当我检测到这些字段(类型实现 IUnit 接口的字段)时,我使用 Any 扩展方法为每个字段设置 NameOfField 属性

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;
  });

:这种方法:

  • 必须通过手动干预调用静态构造函数,然后才能访问任何 Unit 字段
  • 。 NameOfField setter 是公共的。就我而言,这没有问题,但应用于其他场景时可能会出现问题。 (我认为设置器可以设为私有并通过进一步反思来调用,但我没有花时间进一步探索该路径。)
  • ...?

不管怎样,也许这个解决方案对其他人有帮助,而不是我。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文