ispiro
ispiro

Reputation: 27673

How to create a reference to a value-field

Is there a way in C# to create a field which is a reference to another field which is a value type?

class myClass
{
    bool b1;

    public void method1(ref bool b)
    {
        b1 = b;
    }
}

I want b1 to reference the value of b, just as b references the value of the original argument, so that changes to b1 will affect the original argument.

EDIT:

What I’m trying to achieve is a myCheckBox class which automatically updates a field. See: How do I change a value argument from within an event handler?

Upvotes: 3

Views: 9925

Answers (4)

Salvatore Previti
Salvatore Previti

Reputation: 9050

Well... there is a very contort way :) of course. That is, using reflection! You cannot get the address of a field, but we can use reflection.

Reflection is slower than accessing directly a field, i warn you. And really, accessing private fields of other classes is a really bad practice! Is however useful sometime for some dirty hacks when you don't have control of code written by other people.

Here the example, but i keep saying, it is not a good practice, is here only for curiosity and for educational purposes!

Fine another way to access your field, using properties or using a class that modify your properties.

// Our FieldReference class that internally uses reflection to get or set a field value.
public class FieldReference<T>
{
    private object ownerObject;
    private FieldInfo fieldInfo;

    public FieldReference(object ownerObject, string fieldName)
    {
        this.ownerObject = ownerObject;
        this.fieldInfo = ownerObject.GetType().GetField(fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
    }

    public FieldReference(object ownerObject, FieldInfo fieldInfo)
    {
        this.ownerObject = ownerObject;
        this.fieldInfo = fieldInfo;
    }

    public T Value
    {
        get { return (T)this.fieldInfo.GetValue(this.ownerObject); }
        set { this.fieldInfo.SetValue(this.ownerObject, value); }
    }
}

// Our dummy class
public class MyClass
{
    // Our field we want to expose.
    private int myField;

    public MyClass(int value)
    {
        this.myField = value;
    }

    // Just a function we use to print the content of myField.
    public override string ToString()
    {
        return this.myField.ToString();
    }
}

class Program
{
    public static void Main()
    {
        // We create our class.
        MyClass mc = new MyClass(5);

        // We print field value, should be 5 :)
        Console.WriteLine(mc.ToString());

        // We create our field reference
        FieldReference<int> fieldref = new FieldReference<int>(mc, "myField");

        // We set the value using field reference.
        // Note, we accessed a private field :)
        fieldref.Value = 100;

        // Now we print the value, should be 100!
        Console.WriteLine(mc.ToString());

        Console.ReadLine();
    }
}

Upvotes: 2

BrokenGlass
BrokenGlass

Reputation: 160902

Not knowing what you would want this for you could use a delegate for this, it does sound like a code smell though:

class myClass
{
    Action<bool> modify;

    public void method1(Action<bool> modify)
    {
        this.modify = modify;
    }

    public void ModifyIt()
    {
        modify(false);
    }
}


bool b1 = true; //b1 is true
var m = new myClass();
m.method1(val => { b1 = val; });
m.ModifyIt(); //b1 is false now

Upvotes: 1

asawyer
asawyer

Reputation: 17808

Sure! Take a look at Eric's answer to this question:

Setting a ref to a member field in C#

As others have pointed out, you cannot store a reference to a variable in a field in C#, or indeed, any CLR language.

Of course you can capture a reference to a class instance that contains a variable easily enough

Upvotes: 3

Oded
Oded

Reputation: 499012

Looks like something that is better solved using delegates/events.

Instead of trying to do the impossible (force value types to behave as reference types), use an event and fire it whenever this value is changed.

Subscribe to this event from the caller/s and you are good to go.

Upvotes: 2

Related Questions