能否动态获取类实例的声明名称并传入构造函数设置类内变量?
如何获取类实例的变量名称并赋值给类的name字段
这个问题挺有意思的——你想要的是获取实例变量的名称(比如代码里的className),而不是Foo类本身的名称对吧?可惜直接在Foo的构造函数里自动拿到这个变量名是做不到的,因为变量名属于编译时的符号信息,运行时CLR不会默认保留,而且构造函数执行时根本不知道是哪个变量在引用它。不过有几个可行的替代方案,我给你慢慢说:
方案1:用nameof手动传入(最推荐)
这是最简单、性能最好的方式,直接用C#的nameof表达式把变量名作为参数传给构造函数。修改后的代码如下:
public class Foo { public string name; // 构造函数接收实例名称参数 public Foo(string instanceName) { name = instanceName; } } public class SomeOtherClass { // 用nameof获取变量名传入 Foo className = new Foo(nameof(className)); public void PrintInstanceName() { Console.WriteLine(className.name); // 输出:className } }
nameof是编译时计算的,不会有运行时性能损耗,而且代码清晰易懂,几乎没有局限性。
方案2:用表达式树自动提取变量名(无需手动传参)
如果你不想每次都手动写nameof,可以用表达式树来捕获变量的名称。这种方式需要写一个静态工厂方法来创建Foo实例:
public class Foo { public string name; // 把构造函数设为私有,强制通过工厂方法创建 private Foo(string instanceName) { name = instanceName; } // 静态工厂方法,通过表达式树提取变量名 public static Foo Create<T>(Expression<Func<T>> expr) { var memberExpression = expr.Body as MemberExpression; if (memberExpression == null) { throw new ArgumentException("请传入一个变量表达式,比如 () => yourVariable"); } // 提取变量的名称 return new Foo(memberExpression.Member.Name); } } public class SomeOtherClass { // 用工厂方法创建实例,传入变量表达式 Foo className = Foo.Create(() => className); public void PrintInstanceName() { Console.WriteLine(className.name); // 输出:className } }
这个方法的原理是通过表达式树捕获变量的成员信息,从而提取出它的名称。不过要注意:
- 这种写法比
nameof复杂,有一定学习成本 - 如果变量是局部变量或者被编译器优化(比如Release模式下),可能会出现异常
- 性能比
nameof稍差,因为表达式树需要运行时解析
为什么直接在构造函数里拿不到变量名?
再补充一下核心原因:变量名是编译阶段的符号,编译后会被转换为内存地址的引用,默认情况下运行时不会保留这些符号名称(除非你开启调试信息并禁用优化,但即使这样,构造函数也无法知道当前是哪个变量在调用它——因为构造函数的执行和变量赋值是两个独立的步骤,构造函数执行时变量还没完成赋值,也没有上下文能关联到变量本身)。
内容的提问来源于stack exchange,提问作者Kyle Michiels
相关产品推荐
相关产品推荐

