0

One class has a field. Second class should be able to reference that field and to change it. Since you cannot get the address of a field in memory, I have to use reflections. But my approach only works on non-encapsulated fields. So basically:

This works:

public class Dummy
{
    public int field;
    public Dummy(int value)
    {
        this.field = value;
    }
}

class Program
{
    public static void Main()
    {
        Dummy d = new Dummy(20);
        //Shows 20
        Console.WriteLine(d.field.ToString());
        d.GetType().GetField("field", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).SetValue(d, 40);
        //It should show 40 now
        Console.WriteLine(d.field.ToString());
    }
}

This doesn't (throws NullReferenceException):

public class Dummy
{
    public int field { get; set; }
    public Dummy(int value)
    {
        this.field = value;
    }
}

class Program
{
    public static void Main()
    {
        Dummy d = new Dummy(20);
        //Shows 20
        Console.WriteLine(d.field.ToString());
        d.GetType().GetField("field", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).SetValue(d, 40);
        //It should show 40 now
        Console.WriteLine(d.field.ToString());
    }
}

Why? How do I fix it? Can I even access an encapsulated object like that? Thank you!

EkoostikMartin
  • 6,831
  • 2
  • 33
  • 62
JTaylor
  • 13
  • 2

3 Answers3

2

It is not a field any longer. Instead of GetField you should use GetProperty method:

d.GetType().GetProperty(...);
Paweł Bejger
  • 6,176
  • 21
  • 26
2

In both cases, you could (and should) write

d.field = 40;

When you want a field to be non-private, you should always make it a property, as in your second example. You should never have public fields. Note that if you need to access a property via reflection, you'd use GetProperty, not GetField.

Community
  • 1
  • 1
Tim S.
  • 55,448
  • 7
  • 96
  • 122
0

Can you be more precise about the use case? Maybe an interface that isolates the properties' accessors is better:

public interface IDummy
{
    int field { get; set; }
}

You'll be able to manipulate the property without knowing anything about the rest of the object. Isn't that what you need when you want to "reference" a single field?

pid
  • 11,472
  • 6
  • 34
  • 63
  • You are surely right but in my case there's too much variety to use interface. I just wanted a class that holds an object reference and when it gets changed - it changes the field / property elsewhere. That thing up there is just a silly example to make it clear to see where's the error. – JTaylor Jan 23 '14 at 20:34
  • Perfect. I guess you'll poll the value then. Needless to say that setters + events are excellent for these cases. I sense you don't have access to the source code and can't get around polling... – pid Jan 23 '14 at 20:44