-1

I have a scenario where I want to pass in a reference of the value type bool (value type marked with ref) to a constructor of an other class and want to update its value in the other class. Something like this. Is there a way to hold the reference of the variable. (I marked things with public, and I know that public variables can be accessed from anywhere)

public class A
{
    public bool Update;
    public void DoSomething()
    {
        B b = new B(ref Update);
    }
}

public class B
{
    private ref bool _val; //Is it possible to create a variable like this. If not is there a way to achieve what I am doing.
    public B(ref bool value)
    {
        _val = value;
    }
    private void UpdateValue()
    {
        _val = true;
    }
}
xanatos
  • 109,618
  • 12
  • 197
  • 280
nikhil
  • 1,578
  • 3
  • 23
  • 52
  • 1
    I am not clear on what you are trying to do. Are you wanting the value of field Update in class A to be changed when field _val in class B is changed? – Russ Jan 06 '21 at 21:26
  • You can't store a `ref` in a class. But something I always wanted is a `boxed bool`. The solution here is to pass through either an object containing the bool or a delegate that can change it in place. – Charlieface Jan 06 '21 at 21:32

3 Answers3

0

Wrap value with the reference type

public class CanUpdate
{
    public bool Value { get; set; }
}

Then

public class B
{
    private readonly CanUpdate _canUpdate;

    public B(CanUpdate value)
    {
        _canUpdate = value;
    }

    private void UpdateValue()
    {
        _canUpdate.Value = true;
    }
}

Class A will "see" value changed by class B

public class A
{
    private CanUpdate CanUpdate;

    public A()
    {
        CanUpdate = new CanUpdate { Value = false };
    }

    public void DoSomething()
    {
        Console.WriteLine(CanUpdate.Value); // false

        var b = new B(CanUpdate);
        b.UpdateValue();

        Console.WriteLine(CanUpdate.Value); // true
    }
}

Having own dedicated type for a value improves readability and makes code more comprehensible for others.

Fabio
  • 31,528
  • 4
  • 33
  • 72
0

If you want the value only once, then just have it once. Delegate from one class to the other, either from A to B or vice versa.

public class A
{
    B b = new B(false);
    public bool Update { 
        get { return b.BooleanValue; }
    }

    public void DoSomething()
    {

    }
}

public class B
{
    public B(bool value)
    {
        _val = value;
    }
    private void UpdateValue()
    {
        _val = true;
    }

    public bool BooleanValue{ 
        get { return _val; }
    }
}

If the use of B is really as temporary as

public void DoSomething()
{
    B b = new B(ref Update);
}

then let B a method of B return the boolean.

Thomas Weller
  • 55,411
  • 20
  • 125
  • 222
0

It doesn't make sense to set a field as a reference type (private ref bool _val;) since it is just a class scoped variable. Property setters don't allow you to add the ref modifier to the automatic value parameter, so that would not work either. Furthermore, you cannot pass a property as a ref parameter (i.e. obj1.Method(ref obj2.Value) will not work).

I think what you are trying to describe is the observer pattern, where observers watch for changes in a subject's state and react. It's similar to an event listener in JavaScript, but instead of watching actions, you are watching state. A simple implementation of this might look like:

public class Subject
{
    private readonly Observer[] Observers;
    private string _val;
    public string Val
    {
        get => _val;
        set
        {
            // Update every observer's value when this is set.
            foreach (Observer o in Observers)
            {
                o.Val = value;
            }
            _val = value;
        }
    }
    public Subject(params Observer[] observers)
    {
        Observers = observers;
    }
}

public class Observer
{
    public string Val { get; set; }
}

// In execution:
var o1 = new Observer();
var o2 = new Observer();
var subject = new Subject(o1, o2);
subject.Val = "hello there";
Console.WriteLine("o1: " + o1.Val);
Console.WriteLine("o2: " + o2.Val);
Console.WriteLine("subject: " + subject.Val);

// Output:
// o1: hello there
// o2: hello there
// subject: hello there

Note this particular case has some limitations since the relationship only works from Subscriber to Observer (i.e., if you change the Observer's Val directly, it won't be reflected by the other observers and further updates to Subject will overwrite any changes to Observer).

Connor Low
  • 5,900
  • 3
  • 31
  • 52
  • I wouldn't say "It doesn't make sense to set a field as a ref", it is only disallowed by ECMA-335 standard because it may leak a stack pointer to the heap. C++ uses it the whole time, but it's unsafe for managed pointers. – Charlieface Jan 06 '21 at 22:06
  • I have WPF app in which I need to update just one boolean property that is bound to a progress bar from a child class. So I didn't want to pass in the entire object as B b=new B(this), I just wanted to see if there was a way to pass in a ref parameter when an action in a child class executes. I also don't want to raise events. I know the observer pattern.Thanks for the help. – nikhil Jan 06 '21 at 23:32