如何在 C# 中获取 class 变量的引用?
How to get the ref of a variable of a class in C#?
如何获取class中变量的引用?我正在尝试获取一个变量的引用,在别处使用它,并需要将更改反映在它的栖息地中。
public class PowerComINC
{
static int IMALF1_A = 0; //INSTRUCTOR MALF ID FOR MISC FUNCTION
static int IMALF2_A = 0; //INSTRUCTOR MALF ID FOR MISC FUNCTION
static int IMFIRE_A = 0; //INSTRUCTOR MALF ID FOR FIRE
public static ref int GetAssociatedGlobals(string variableName)
{
// return ref of variableName
}
}
...
ref int val = ref PowerComINC.GetAssociatedGlobals("IMALF1_A");
val++;
Console.Writeln(PowerComINC.IMALF1_A); //Print 1
您可以简单地创建一个 Dictionary<string, int>
,而不是依赖变量的名称,将这些信息保存为字符串对和 int
。那么你就不需要所有这些 ref
-stuff at al:
public class PowerComINC
{
public Dictionary<string, int> MyDict = new Dictionary<string, int>()
{
{ "IMALF1_A", 0 },
{ "IMALF2_A", 0 },
{ "IMFIRE_A", 0 }
};
}
现在只需通过键引用一个值:
Console.Writeln(PowerComINC.MyDict("IMALF1_A")); //Print 1
根据您的评论:您仍然可以使用反射填充的词典:
myDict = typeof(PowerComINC).GetFields(BindingFlags.Static | BindingFlags.NonPublic).ToDictionary(x => x.Name, x => x)
这为您提供了一个包含变量名称的字典和一个代表字段的 FieldInfo
实例,然后您可以使用它来获取实际值:
myDict["IMALF1_A"].GetValue(null);
你甚至可以把它改成Dictionary<string, Func<int>>
,这样你就可以直接得到变量值:
myDict = typeof(PowerComINC).GetFields(BindingFlags.Static | BindingFlags.NonPublic)
.ToDictionary(x => x.Name, x => new Func<int>(() => (int) x.GetValue(null));
您现在可以使用此调用 - 诚然很奇怪 - 语法:
var i = myDict["IMALF1_A"]();
你是怎么做到的? Like so:
ref int val = ref PowerComINC.GetAssociatedGlobals("IMALF1_A");
val++;
Console.WriteLine(PowerComINC.IMALF1_A);
请注意在变量声明和赋值前缀中使用 ref
。 (您也可以使用 ref var val = ...
,即类型将被隐式确定,但仍然需要 ref
)。
你的方法大概是这样实现的:
public class PowerComINC
{
internal static int IMALF1_A = 0; //INSTRUCTOR MALF ID FOR MISC FUNCTION
internal static int IMALF2_A = 0; //INSTRUCTOR MALF ID FOR MISC FUNCTION
internal static int IMFIRE_A = 0; //INSTRUCTOR MALF ID FOR FIRE
public static ref int GetAssociatedGlobals(string variableName)
{
switch (variableName)
{
case "IMALF1_A":
return ref IMALF1_A;
case "IMALF2_A":
return ref IMALF2_A;
case "IMFIRE_A":
return ref IMFIRE_A;
}
throw new ArgumentException(nameof(variableName));
}
}
然而,正如 HimBromBeere 所说,以这种方式解决这个问题毫无意义。 switch
查找的性能下降总是会超过直接修改像 int 这样小的引用变量的任何性能优势,现在你没有任何字段的封装。
您可以避免使用字典或开关,而是在对象的字段中使用搜索,而不是使用 Type 对象的 GetField() 方法。
所有这些 ref 的东西都非常复杂,我发现没有办法从 GetField().GetValue() 结果中得到 ref,所以我宁愿建议你只做 getter 和 setter为此。
由于您的 class 是静态的,您必须使用 typeof 关键字
而且您的变量不能是私有的,这样才能用 GetField()
public static int getval (string varname)
{
return (int)typeof(PowerComINC).GetField(varname).GetValue(typeof(int));
}
public static void setval(string varname, int value)
{
typeof(PowerComINC).GetField(varname).SetValue(typeof(int), value);
}
然后在你的方法中使用
int val = getval("IMALF1_A");
val++;
setval("IMALF1_A", val);
如何获取class中变量的引用?我正在尝试获取一个变量的引用,在别处使用它,并需要将更改反映在它的栖息地中。
public class PowerComINC
{
static int IMALF1_A = 0; //INSTRUCTOR MALF ID FOR MISC FUNCTION
static int IMALF2_A = 0; //INSTRUCTOR MALF ID FOR MISC FUNCTION
static int IMFIRE_A = 0; //INSTRUCTOR MALF ID FOR FIRE
public static ref int GetAssociatedGlobals(string variableName)
{
// return ref of variableName
}
}
...
ref int val = ref PowerComINC.GetAssociatedGlobals("IMALF1_A");
val++;
Console.Writeln(PowerComINC.IMALF1_A); //Print 1
您可以简单地创建一个 Dictionary<string, int>
,而不是依赖变量的名称,将这些信息保存为字符串对和 int
。那么你就不需要所有这些 ref
-stuff at al:
public class PowerComINC
{
public Dictionary<string, int> MyDict = new Dictionary<string, int>()
{
{ "IMALF1_A", 0 },
{ "IMALF2_A", 0 },
{ "IMFIRE_A", 0 }
};
}
现在只需通过键引用一个值:
Console.Writeln(PowerComINC.MyDict("IMALF1_A")); //Print 1
根据您的评论:您仍然可以使用反射填充的词典:
myDict = typeof(PowerComINC).GetFields(BindingFlags.Static | BindingFlags.NonPublic).ToDictionary(x => x.Name, x => x)
这为您提供了一个包含变量名称的字典和一个代表字段的 FieldInfo
实例,然后您可以使用它来获取实际值:
myDict["IMALF1_A"].GetValue(null);
你甚至可以把它改成Dictionary<string, Func<int>>
,这样你就可以直接得到变量值:
myDict = typeof(PowerComINC).GetFields(BindingFlags.Static | BindingFlags.NonPublic)
.ToDictionary(x => x.Name, x => new Func<int>(() => (int) x.GetValue(null));
您现在可以使用此调用 - 诚然很奇怪 - 语法:
var i = myDict["IMALF1_A"]();
你是怎么做到的? Like so:
ref int val = ref PowerComINC.GetAssociatedGlobals("IMALF1_A");
val++;
Console.WriteLine(PowerComINC.IMALF1_A);
请注意在变量声明和赋值前缀中使用 ref
。 (您也可以使用 ref var val = ...
,即类型将被隐式确定,但仍然需要 ref
)。
你的方法大概是这样实现的:
public class PowerComINC
{
internal static int IMALF1_A = 0; //INSTRUCTOR MALF ID FOR MISC FUNCTION
internal static int IMALF2_A = 0; //INSTRUCTOR MALF ID FOR MISC FUNCTION
internal static int IMFIRE_A = 0; //INSTRUCTOR MALF ID FOR FIRE
public static ref int GetAssociatedGlobals(string variableName)
{
switch (variableName)
{
case "IMALF1_A":
return ref IMALF1_A;
case "IMALF2_A":
return ref IMALF2_A;
case "IMFIRE_A":
return ref IMFIRE_A;
}
throw new ArgumentException(nameof(variableName));
}
}
然而,正如 HimBromBeere 所说,以这种方式解决这个问题毫无意义。 switch
查找的性能下降总是会超过直接修改像 int 这样小的引用变量的任何性能优势,现在你没有任何字段的封装。
您可以避免使用字典或开关,而是在对象的字段中使用搜索,而不是使用 Type 对象的 GetField() 方法。
所有这些 ref 的东西都非常复杂,我发现没有办法从 GetField().GetValue() 结果中得到 ref,所以我宁愿建议你只做 getter 和 setter为此。
由于您的 class 是静态的,您必须使用 typeof 关键字
而且您的变量不能是私有的,这样才能用 GetField()
public static int getval (string varname)
{
return (int)typeof(PowerComINC).GetField(varname).GetValue(typeof(int));
}
public static void setval(string varname, int value)
{
typeof(PowerComINC).GetField(varname).SetValue(typeof(int), value);
}
然后在你的方法中使用
int val = getval("IMALF1_A");
val++;
setval("IMALF1_A", val);