I'm attempting to use
Reflection.FieldInfo.SetValue
to modify a structure's integer field value. However, it doesn't get modified.
I realize, that SetValue expects an Object and that just giving it a value is working with a copy, but boxing the integer doesn't help either.
What is my mistake?
What I have tried:
Here's ready to copy and paste code in C# (further below in VB as well):
using
System;
using
System.Reflection;
public
static
class
Test
public
struct
SStruct
public
int
Value;
public
static
void
Main()
SStruct rStruct =
new
SStruct();
rStruct.Value =
42
;
Type tStruct =
typeof
(SStruct);
FieldInfo fValue = tStruct.GetField(
"
Value"
);
object
oValue = fValue.GetValue(rStruct);
Console.WriteLine(
"
Read Value Before Mod: {0}"
, oValue);
fValue.SetValue(rStruct,
21
);
oValue = fValue.GetValue(rStruct);
Console.WriteLine(
"
Read Value After Mod: {0}"
, oValue);
object
oStruct = rStruct;
fValue.SetValue(oStruct,
21
);
oValue = fValue.GetValue(rStruct);
Console.WriteLine(
"
Read After Boxing: {0}"
, oValue);
Console.Read();
Here VB:
Imports System
Imports System.Reflection
Module Test
Public Structure SStruct
Public Value As Integer
End Structure
Public Sub Main()
'
Initialize a structure record.
Dim rStruct As New SStruct
rStruct.Value = 42
'
Reading the Value field by name:
Dim tStruct As Type = GetType(SStruct)
Dim fValue As FieldInfo = tStruct.GetField(
"
Value"
)
Dim oValue As
Object
= fValue.GetValue(rStruct)
Console.WriteLine(
"
Read Value Before Mod: {0}"
, oValue)
'
Attempting to modify the Value field:
fValue.SetValue(rStruct, 21)
oValue = fValue.GetValue(rStruct)
Console.WriteLine("Read Value After Mod: {0}", oValue)
'
It didn
'
t change.
'
SetValue
is
expecting an
object
though. Box the
struct
.
Dim oStruct As
Object
= rStruct
fValue.SetValue(oStruct,
21
)
oValue = fValue.GetValue(rStruct)
Console.WriteLine(
"
Read After Boxing: {0}"
, oValue)
'
It didn'
t change.
Console.Read()
End Sub
End Module
Edit:
Unboxing as suggested by Chris Copeland seems to do the trick in C#, but why does it not work in our VB enviroment? Check it out online on
dotnetfiddle.net
: C# produces 42,42,21 with this:
using
System;
using
System.Reflection;
public
static
class
Test
public
struct
SStruct
public
int
Value;
public
static
void
Main()
SStruct rStruct =
new
SStruct();
rStruct.Value =
42
;
Type tStruct =
typeof
(SStruct);
FieldInfo fValue = tStruct.GetField(
"
Value"
);
object
oValue = fValue.GetValue(rStruct);
Console.WriteLine(
"
Read Value Before Mod: {0}"
, oValue);
fValue.SetValue(rStruct,
21
);
oValue = fValue.GetValue(rStruct);
Console.WriteLine(
"
Read Value After Mod: {0}"
, oValue);
object
boxed = (
object
)rStruct;
fValue.SetValue(boxed,
21
);
rStruct = (SStruct)boxed;
oValue = fValue.GetValue(rStruct);
Console.WriteLine(
"
Read After Boxing: {0}"
, oValue);
but 42,42,42 in VB:
Imports System
Imports System.Reflection
Public Module Test
Public Structure SStruct
Public Value As Integer
End Structure
Public Sub Main()
'
Initialize a structure record.
Dim rStruct As New SStruct
rStruct.Value = 42
'
Reading the Value field by name:
Dim tStruct As Type = GetType(SStruct)
Dim fValue As FieldInfo = tStruct.GetField(
"
Value"
)
Dim oValue As
Object
= fValue.GetValue(rStruct)
Console.WriteLine(
"
Read Value Before Mod: {0}"
, oValue)
'
Attempting to modify the Value field:
fValue.SetValue(rStruct, 21)
oValue = fValue.GetValue(rStruct)
Console.WriteLine("Read Value After Mod: {0}", oValue)
'
It didn
'
t change.
'
SetValue
is
expecting an
object
though. Box the
struct
.
Dim oStruct As
Object
= CType(rStruct,
Object
)
fValue.SetValue(oStruct,
21
)
rStruct = CType(oStruct, SStruct)
oValue = fValue.GetValue(rStruct)
Console.WriteLine(
"
Read After Boxing: {0}"
, oValue)
'
It didn'
t change.
End Sub
End Module
A
struct
is a pass-by-value object, which means that anytime it gets passed into a method as an argument a new instance of the
struct
is created, and that will receive the updates. So when you call
fValue.SetValue(rStruct, 21);
what this is doing is creating a
new
instance of
SStruct
, and the field is modified in that.
A solution to this is to box the structure, and then unbox afterwards, like so:
object
boxed = (
object
)rStruct;
fValue.SetValue(boxed,
21
);
rStruct = (SStruct)boxed;
Read the question carefully.
Understand that English isn't everyone's first language so be lenient of bad
spelling and grammar.
If a question is poorly phrased then either ask for clarification, ignore it, or
edit the question
and fix the problem. Insults are not welcome.
Don't tell someone to read the manual. Chances are they have and don't get it.
Provide an answer or move on to the next question.
Let's work to help developers, not make them feel stupid.