FeildInfo.SetValue(object obj,object value) 不改变对象的字段
FeildInfo.SetValue(object obj,object value) make no change to field of object
我一直在尝试使用反射动态分配给结构,以将文件读入命名字符串的结构,但是该过程无法将分配的值加载到结构参数中。
下面的代码有同样的问题,任何关于为什么 testints 字段没有被这个过程更新的见解将不胜感激
using System.Threading;
using System.Reflection;
namespace Reflection_Testing
{
struct testints
{
public int t1;
public int t2;
public int t3;
public int t4;
public int t5;
}
class Program
{
static void Main(string[] args)
{
testints test1 = new testints();
foreach (var feild in test1.GetType().GetFields())
{
feild.SetValue(test1, 17);
}
foreach (var feild in test1.GetType().GetFields())
{
Console.WriteLine("print test 1");
Console.WriteLine(feild.GetValue(test1));
}
}
}
}
预期输出:
print test 1
17
print test 1
17
print test 1
17
print test 1
17
print test 1
17
实际输出:
print test 1
0
print test 1
0
print test 1
0
print test 1
0
print test 1
0
首先,我建议在几乎所有情况下避免使用可变结构。如果这是 class,你会没事的,因为不会涉及拳击。
问题是每次你执行这个:
feild.SetValue(test1, 17);
你是 boxing test1
- 在内存中创建一个新对象,它是 test1
的 copy,并传递一个引用该对象到 SetValue
方法。该字段将在该对象上设置 - 但您不再拥有对该对象的引用,因此您永远不会看到它。
如果您装箱 一次,对装箱对象进行所有更改,然后取消装箱或仅对装箱对象调用 GetField
,它将给出你期望的输出:
using System;
using System.Reflection;
struct TestInts
{
public int t1;
public int t2;
public int t3;
public int t4;
public int t5;
}
class Program
{
static void Main()
{
TestInts test1 = new TestInts();
// Box the value once
object boxed = test1;
foreach (var field in test1.GetType().GetFields())
{
field.SetValue(boxed, 17);
}
foreach (var field in test1.GetType().GetFields())
{
Console.WriteLine($"{field.Name}: {field.GetValue(boxed)}");
}
}
}
如果您想要将值返回到您的 test1
变量中,您需要拆箱:
test1 = (TestInts) boxed;
您可以使用下一个代码实现所需的行为(因此在这里将 testints
声明为 class
似乎更合适,请阅读 this and this 指南):
object test1 = new testints();
foreach (var feild in test1.GetType().GetFields())
{
feild.SetValue(test1, 17);
}
foreach (var feild in test1.GetType().GetFields())
{
Console.WriteLine("print test 1");
Console.WriteLine(feild.GetValue(test1));
}
这将 box test1
and pass it to GetValue
/SetValue
accepting an object
. Also take into account that even without boxing struct
's are passed by value(a copy is created and passed to method), so the next will also fail without ref
修饰符:
static void Set(testints t)
{
t.t1 = 17;
}
var test2 = new testints();
Set(test2);
Console.WriteLine(test2.t1); // prints "0"
我一直在尝试使用反射动态分配给结构,以将文件读入命名字符串的结构,但是该过程无法将分配的值加载到结构参数中。 下面的代码有同样的问题,任何关于为什么 testints 字段没有被这个过程更新的见解将不胜感激
using System.Threading;
using System.Reflection;
namespace Reflection_Testing
{
struct testints
{
public int t1;
public int t2;
public int t3;
public int t4;
public int t5;
}
class Program
{
static void Main(string[] args)
{
testints test1 = new testints();
foreach (var feild in test1.GetType().GetFields())
{
feild.SetValue(test1, 17);
}
foreach (var feild in test1.GetType().GetFields())
{
Console.WriteLine("print test 1");
Console.WriteLine(feild.GetValue(test1));
}
}
}
}
预期输出:
print test 1
17
print test 1
17
print test 1
17
print test 1
17
print test 1
17
实际输出:
print test 1
0
print test 1
0
print test 1
0
print test 1
0
print test 1
0
首先,我建议在几乎所有情况下避免使用可变结构。如果这是 class,你会没事的,因为不会涉及拳击。
问题是每次你执行这个:
feild.SetValue(test1, 17);
你是 boxing test1
- 在内存中创建一个新对象,它是 test1
的 copy,并传递一个引用该对象到 SetValue
方法。该字段将在该对象上设置 - 但您不再拥有对该对象的引用,因此您永远不会看到它。
如果您装箱 一次,对装箱对象进行所有更改,然后取消装箱或仅对装箱对象调用 GetField
,它将给出你期望的输出:
using System;
using System.Reflection;
struct TestInts
{
public int t1;
public int t2;
public int t3;
public int t4;
public int t5;
}
class Program
{
static void Main()
{
TestInts test1 = new TestInts();
// Box the value once
object boxed = test1;
foreach (var field in test1.GetType().GetFields())
{
field.SetValue(boxed, 17);
}
foreach (var field in test1.GetType().GetFields())
{
Console.WriteLine($"{field.Name}: {field.GetValue(boxed)}");
}
}
}
如果您想要将值返回到您的 test1
变量中,您需要拆箱:
test1 = (TestInts) boxed;
您可以使用下一个代码实现所需的行为(因此在这里将 testints
声明为 class
似乎更合适,请阅读 this and this 指南):
object test1 = new testints();
foreach (var feild in test1.GetType().GetFields())
{
feild.SetValue(test1, 17);
}
foreach (var feild in test1.GetType().GetFields())
{
Console.WriteLine("print test 1");
Console.WriteLine(feild.GetValue(test1));
}
这将 box test1
and pass it to GetValue
/SetValue
accepting an object
. Also take into account that even without boxing struct
's are passed by value(a copy is created and passed to method), so the next will also fail without ref
修饰符:
static void Set(testints t)
{
t.t1 = 17;
}
var test2 = new testints();
Set(test2);
Console.WriteLine(test2.t1); // prints "0"