提问人:user999666 提问时间:9/19/2023 最后编辑:user999666 更新时间:9/19/2023 访问量:71
通过将静态字段作为方法参数传递来更新静态字段
Updating a static field by passing it as a method argument
问:
我的应用程序将涉及对静态字段的大量修改。我想知道如何通过将不同类的静态字段作为方法参数传递给实用程序 setter 方法来更新它们。
internal static class Hero1
{
public static bool awesomeAbility = false;
public static bool anotherAwesomeAbility = false;
}
internal static class Hero2
{
public static bool awesomeAbility = false;
public static bool anotherAwesomeAbility = false;
}
internal static class Utils
{
public static async void ToggleAbility(ability, bool value)
{
Logger.Write($@"{ability} = {value}");
ability = value;
}
}
// example usage....
ToggleAbility(Hero1.awesomeAbility, true);
ToggleAbility(Hero2.anotherAwesomeAbility, false);
答:
1赞
lidqy
9/19/2023
#1
嗨,您需要关键字才能实际更改所属类(静态或非静态)中的字段值。否则,您只需更改副本,该副本在调用方法后就会被转移。ref
但是,它不能再是异步的。
internal static class Utils
{
public static void ToggleAbility(ref bool ability, bool value)
{
Logger.Write($@"{ability} = {value}");
ability = value;
}
}
ToggleAbility(ref Hero1.awesomeAbility, true);
ToggleAbility(ref Hero2.anotherAwesomeAbility, false);
1赞
Sweeper
9/19/2023
#2
如果允许调用方传递表达式树 (),则可以执行此操作,然后可以将表达式树引用的字段作为 .Expression<Func<bool>>
FieldInfo
async void ToggleAbility(Expression<Func<bool>> field, bool value) {
if (field.Body is MemberExpression memberExpression &&
memberExpression.Member is FieldInfo fieldInfo) {
// instead of field.Body, you can also use fieldInfo.Name for a simple name
Logger.Write($@"{field.Body} = {fieldInfo.GetValue(null)}");
// this sets the field's value
fieldInfo.SetValue(null, value);
// if you want to set it back asynchronously some time later...
// await Task.Delay(...);
// fieldInfo.SetValue(null, !value);
} else {
// the expression tree is not an access to a public static field
// you could e.g. throw an exception
}
}
用法:
ToggleAbility(() => Hero1.awesomeAbility, true);
设置字段不是很快。如果这对您来说是个问题,您可以选择“现场设置器”SetValue
Action<bool>
async void ToggleAbility(Action<bool> setter, bool value) {
setter(value)
await Task.Delay(...);
setter(!vakue)
}
ToggleAbility(x => Hero1.awesomeAbility = x, true);
但是,您无法使用此方法访问字段名称或其当前值,除非您还将它们作为其他参数传入:ToggleAbility
ToggleAbility(
x => Hero1.awesomeAbility = x,
true,
nameof(Hero1.awesomeAbility),
Hero1.awesomeAbility);
如果你的方法不需要是异步的,你也可以将该字段作为参数传入,如 lidqy 的答案所示。ref
评论
0赞
lidqy
9/19/2023
这真是太棒了,因为它非常慢,并且需要大量代码才能完成简单的任务,以便为字段赋值;)
0赞
lidqy
9/19/2023
怎么样:调用为:async void ToggleAbility(Action<bool> setter, bool value) => setter(value);
await ToggleAbility( val => Hero1.awesomeAbility = val, true);
0赞
lidqy
9/19/2023
最后,为什么不直接做:?Hero1.awesomeAbility = true
0赞
Sweeper
9/19/2023
@lidqy OP 似乎正在将一些通用逻辑提取到此方法中 - 它不仅仅是设置字段。采取确实有效 - 我个人不喜欢一直重写。也许我应该把它作为替代方案加进去。ToggleAbility
Action<bool>
= val
0赞
Sweeper
9/19/2023
@lidqy 实际上,仅仅取一个是行不通的,因为 OP 想要访问方法中字段的名称和值。Action
评论