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,721
  • 2
  • 31
  • 60
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
  • 5,976
  • 20
  • 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.
  • 53,874
  • 7
  • 89
  • 119
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,182
  • 5
  • 35
  • 58
  • 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