【问题标题】:how do i get a class name variable我如何获得一个类名变量
【发布时间】:2019-08-30 12:28:28
【问题描述】:

我正在尝试获取类变量名

static void Main()
{
    TaskAction m_first = new TaskAction();
    m_first.Increment();
    m_first.Increment();

    TaskAction m_Second = new TaskAction();
    m_Second.Increment();

}

public class TaskAction
{
    private int m_Current;

    public TaskAction()
    {
        m_Current = 0;

    }

    public void Increment()
    {
        m_Current++;
        write(" TaskAction " + vairableName + " "  + m_Current);       
    }
}

我想把它写出来:

TaskAction m_first 1

TaskAction m_first 2

TaskAction m_second 1

【问题讨论】:

  • 不能,变量名不会编译到程序集中。一个更大的问题:你为什么要这样做?
  • 你不能从 TaskAction 类内部执行此操作。
  • 你不能这样做吗?您要解决的问题是什么?
  • 试图改进日志系统
  • 为什么不将变量名称作为参数提供给TaskActon 的构造函数?顺便说一句:当用户使用new TaskAction().Increment() 时,你会期待什么?那么正在创建的实例甚至根本没有分配给变量,所以在这里获取名称是没有意义的。

标签: c# reflection


【解决方案1】:

像这样检索有关程序的元数据既复杂又不必要,只需将名称传递给构造函数即可。

static void Main()
{
    TaskAction m_first = new TaskAction("m_first");
    m_first.Increment();
    m_first.Increment();

    TaskAction m_Second = new TaskAction("m_Second");
    m_Second.Increment();

}

public class TaskAction
{
    private int m_Current;
    private string m_taskName;

    public TaskAction(string taskName)
    {
        m_taskName = taskName;
        m_Current = 0;
    }

    public void Increment()
    {
        m_Current++;
        write(" TaskAction " + m_taskName + " "  + m_Current);       
    }
}

【讨论】:

    【解决方案2】:

    简答:你不能。

    长答案:

    从技术上讲,可以通过检查 IL(由 C# 编译器创建的中间语言)来确定变量名称,但此操作很难且容易出错。此外,您忽略了一些重要问题:

    • 首先,正如这里已经问过的:为什么?这样的事情将如何增强您的程序?

    • 类的每个实例都可以有多个指向它的变量(请参阅我关于 .NET 中类型的回答 here)。你想得到其中的哪一个?例如,考虑以下程序:

    var v1 = new TaskAction();
    var c2 = new TaskAction();
    c1.Increment(); // 1 c1
    c2 = c1;
    c2.Increment(); // 2 c1? 2 c2? 2 c1 c2?
    
    • 这样做会以一种困难的方式破坏封装——任何反射都会破坏封装,除非你真的需要它,否则真的不要使用它——但是这么多?反射打破了私有接口的隐藏信息,你的问题打破了内部接口!

    由于你没有提供足够的信息,我不知道你为什么坚持你需要那个。但这里有一些解决方案:

    • 例如,如果您想要使用类别进行日志记录 - 只需将类别传递给构造函数,如上所示。

    • 1234563 987654323@/as,例如:
    if (this is Drived)
    {
        ((Drived)this).SomeDrivedMethod();
    }
    

    请注意,它违反了 OOP 原则:一个类不应该知道它的驱动类。

    希望这对您有所帮助。祝你有美好的一天!

    编辑:

    出于您的目的,您可以执行以下操作之一:

    最好 - 调试您的代码,查看调用堆栈等

    更糟 - 打印调用者方法名称,而不是对象名称。可以使用System.Runtime.CompilerServices.CallerMemberNameAttribute

    void Increment([System.Runtime.CompilerServices.CallerMemberName] string caller = null)
    {
        // Default value to `caller` is neccessary
        // ...
        Console.WriteLine("Caller: {0}", caller);
    }
    

    注意:编译器填充caller参数,而不是在运行时。

    【讨论】:

    • 完整的 TaskAction 在很多地方被调用,所以我想跟踪 Increment() 何时被调用,因为它们在回调中被调用。我想要一种简单的方法来弄清楚他们何时被调用,
    【解决方案3】:

    如果要唯一标识类对象或使用自定义构造函数为类提供名称,请​​获取 object.GetHashCode()。

    【讨论】:

    • 哈希码并不是唯一的。除此之外,您的解决方案似乎并不是 OP 想要实现的。
    • 根据您的评论“为什么不将变量名称作为参数提供给 TaskActon 的构造函数?”就是我所说的“使用自定义构造函数为类提供名称”。
    猜你喜欢
    • 1970-01-01
    • 2014-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-09
    • 2015-05-07
    • 1970-01-01
    相关资源
    最近更新 更多