FieldInfo.SetValue()

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

FieldInfo.SetValue() doesn't appear to work when trying to set the values of fields of a struct. Why? Because structs are passed by value and not reference?
 
Yeah that's interesting actually.
If you box the struct first it works, eg.

public struct test
{
public string name;
}

static void Main()
{
test t = new test();
FieldInfo fi = t.GetType().GetField("name");
object p = (object)t;
fi.SetValue(p, "blah");
t = (test)p;
Console.WriteLine(t.name);
Console.ReadLine();
}


Glen said:
FieldInfo.SetValue() doesn't appear to work when trying to set the values
of fields of a struct. Why? Because structs are passed by value and not
reference?
 
Glen said:
FieldInfo.SetValue() doesn't appear to work when trying to set the
values of fields of a struct. Why?

You need to take boxing into account. Here's an example:

using System;
using System.Reflection;

struct Foo
{
public int x;

public void Show()
{
Console.WriteLine(x);
}
}

public class Test
{
static void Main()
{
Foo foo = new Foo();
foo.x = 3;
foo.Show();

FieldInfo fi = typeof(Foo).GetField("x");

object boxed = foo;
fi.SetValue (boxed, 5);
foo = (Foo) boxed;

foo.Show();
}
}
Because structs are passed by value and not reference?

Everything is passed by value by default in C#.
See http://www.pobox.com/~skeet/csharp/parameters.html
 
Glen said:
FieldInfo.SetValue() doesn't appear to work when trying to set the values
of fields of a struct. Why? Because structs are passed by value and not
reference?

If you box a struct, it gets copied: the original version lives in the
stack, while the boxed version is in the heap, so after boxing, you actually
got 2 structures. If the box'ed version is modified, this doesn't touch the
original version. As FieldInfo.SetValue takes an 'object' parameter, the
struct gets boxed when you pass it, and the stack-version never gets
changed. It's a bit weird, but I think the behaviour is correct.

Every boxing/unboxing creates a copy of the data. Consider the following:
In this sample, neither the boxed, nor the stack version of "foo" is
changed!

using System;
using System.Reflection;

struct Foo
{
public int x;

public void SetX(int i) { x = i; }

public void Show() { Console.WriteLine(x); }
}

public class Test
{
static void Main()
{
Foo foo = new Foo();
foo.x = 3;
foo.Show();

object boxed = foo;
((Foo)boxed).SetX(5); // the cast unboxes "boxed", and only the
member of the temporary unboxed version is modified, so this is really a
no-op
((Foo)boxed).Show();
foo = (Foo) boxed;

foo.Show();

Console.ReadLine();
}
}

Niki
 
Back
Top