1

What is the problem here? For some reason, the method EditInfo does not change the values of variables.

struct Address
{
    public string id;
    public string addressline;
    public string postalcode;

    public Address(string[] data)
    {
        this.id = data[0];
        this.addressline = data[1];
        this.postalcode = data[2];
    }

    public void EditInfo(string field, string newdata)
    {
        Type myType = typeof(Address);
        myType.GetField(field).SetValue(this, newdata);
    }
}
Bohdan
  • 23
  • 3
  • 1
    Any reason you are using a `struct` and not a `class`. Mutating structs often results in surprises – Flydog57 Feb 11 '21 at 17:54
  • Can you provide an example of you attempting to use "EditInfo"? Also, can you be any more specific apart from "does not work", maybe a stacktrace if possible? – Frontear Feb 11 '21 at 18:13
  • I'm curious, in this context, what is "vector"? Is it System.Numerics.Vector. That seems designed for use with numeric quantities (its one-line description is _Represents a single vector of a specified numeric type that is suitable for low-level optimization of parallel algorithms._) – Flydog57 Feb 11 '21 at 18:14
  • @Frontear: Surprisingly, in this case "doesn't work" is a pretty fair description. Create an `Address` with the constructor, call `EditInfo` on the `Address` you have and nothing seems to happen. John Wu's answer explains why. – Flydog57 Feb 11 '21 at 18:16

2 Answers2

2

It's tricky to update structs via reflection because you're usually working with a boxed value, which is immediately lost. See this answer for a little more info.

The simplest fix in your case is to change your struct to a class, and then your original code will work.

But if you insist on having a struct, you'll need to use the undocumented __makeref and a typed reference update using SetValueDirect, like this:

public void EditInfo(string field, string newdata)
{
    Type myType = typeof(Address);
    var fieldInfo = myType.GetField(field);
    var reference = __makeref(this);
    fieldInfo.SetValueDirect(reference, newdata);
}
John Wu
  • 50,556
  • 8
  • 44
  • 80
0

One solution is to avoid Reflection altogether (of course the real solution is to avoid using a mutable value type). Replacing EditInfo with this seems to work:

public void EditInfo(string field, string newdata)
{
    switch (field)
    {
        case nameof(id):
            id = newdata;
            break;
        case nameof(addressline):
            addressline = newdata;
            break;
        case nameof(postalcode):
            postalcode = newdata;
            break;
        default:
            throw new Exception("oops");
    }
}

You are doing a field lookup by name, so this is likely about the same amount of work, but without the abstraction and boxing/unboxing overhead of Reflection.

Just an idea

Flydog57
  • 6,851
  • 2
  • 17
  • 18