Jump to content
  • Advertisement
Sign in to follow this  

c# Tieing variables

This topic is 1326 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

The problem I am trying to figure out has to do with passing variables about a variable geometry network.

 

Say you have three components. A B C, each has input variables and output variables.

 

A has three inputs a1,a2,a3  and generates three values A1,A2,A3

B has three inputs a1,b1,A3 and generates three values B1,B2,B3

C has three inputs c1,B2,A2 and generates three values C1,C2,C3

 

Because of the nature of the code, I could have hundreds of these things and I am trying to come up with a way of linking them together.

 

In C++ I would just take a pointer to A3 as an input to function B, then whenever B runs it has the latest value 

The same for B2 and A2 in function C

 

(actually I normally have a dependency manager and ref counted variables so the network can be dynamic, but that's out of the scope of this question)

 

However I want to avoid using unsafe mode if I can.

 

Any of you come across a nice clean solution to this issue ?

Share this post


Link to post
Share on other sites
Advertisement


In C++ I would just take a pointer to A3 as an input to function B, then whenever B runs it has the latest value 

 

So are you trying to do something like this?

// C++
class A
{
public:
   void SomethingThatUpdatesA3();

   int A3;

}

class B
{
public:
    B(int* a3)
    : a3_(a3)
    {}

    void Run()
    {
        cout << *a3_;
    }

    int* a3_;
}

You could use a delegate to achieve something like that in c#

// C#
class A
{
   public void SomethingThatUpdatesA3();

   public int A3 {get;set;}
}

class B
{
    public B(Func<int> getA3)
    {
        _getA3 = getA3;
    }

    public void Run()
    {
        Console.Write(_getA3());
    }

    public Func<int> _getA3;
}

int main()
{
    var a = new A();
    var b = new B(() => a.A3);
     
    a.SomethingThatUpdatesA3();
    b.Run();

}

There are probably better ways of doing that if you explain what you're trying to achieve more clearly

Share this post


Link to post
Share on other sites

I'm not really sure what the problem or question is, but I think what you are describing falls under the term reactive programming.
 
This seems like it could be what you are looking for but I have only seen it myself as of 5 minutes ago: Reactive Extensions
 
If you want to build something yourself I'd suggest encapsulating the inputs in a class. That way you can still store references to them, update them and have the values updated in the nodes that use them.
 

// pseudocode
class Value<T> {
    event valueChanged; // notifies event change
    property T value {get; set; } // call event delegates when set
}
Edited by Madhed

Share this post


Link to post
Share on other sites

Yes reactive programming seems to be the basic principle I need.

 

I don't want to have events flying around though, I'm thinking now I can simply have a class as a new type.

 

something along the lines of.  (not tested yet, not even sure it would compile, but you get the idea rolleyes.gif )

class Variable
{
      List<ref object> tied_objects = new List<ref object>();
      object _value;

      object value {
            get {return _value;}
            set {
                _value=Value;
                foreach (ref object o in tied_objects)
                    o = _value;
            }

      }
}


Share this post


Link to post
Share on other sites
How about actually using the same reference when they're shared?
 
using System.Collections.Generic;
using System.Linq;

class Variable
{
    public object Value;
}

class Component
{
    public List<Variable> Inputs;
    public List<Variable> Outputs;

    public Component(int numInputs, int numOutputs)
    {
        // (LINQ shorthand for: 'Inputs = new List<Variable>(numInputs); for (int i=0; i<numInputs; ++i) Inputs[i] = new Variable();')
        Inputs = Enumerable.Range(0, numInputs).Select(x => new Variable()).ToList();
        Outputs = Enumerable.Range(0, numOutputs).Select(x => new Variable()).ToList();
    }

    public virtual void Update()
    {
        // Read from the various Inputs[x].Values and Write to the various Outputs[x].Values
    }

    public void Update(params object[] inputValues)
    {
        for (int i=0; i<inputValues.Length && i < Inputs.Count; ++i)
            Inputs[i].Value = inputValues[i];

        Update();
    }
}

class Program
{
    static void Main(string[] args)
    {
        Component A = new Component(3,3);
        Component B = new Component(3,3);
        Component C = new Component(3,3);

        // Since "Variable" is a reference type, they can be shared directly.
        B.Inputs[2] = A.Outputs[2];

        C.Inputs[1] = B.Outputs[1];
        C.Inputs[2] = A.Outputs[1];
    }
}
The potential downside of this is that the effect is bidirectional; If your code sets an input that's tied to a different component's output, the output value will change (obviously, since the variable is the same).

If you never explicitly set the value of a tied output, this will work fine. Otherwise, you can easily introduce strange bugs, especially if your component graph forks a lot.

If you want data to only flow one way, events are the easiest way. Edited by Nypyren

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!