Referencing value-types?

Is there a way to reference value-type variables without using pointers or wrapper classes?

Like I don’t want to use:

//not this (especially considering unsafe code)
int* stuff;

//and probably not this
public class Things
{
    int stuff;
}

I’m working on an editor so I can adjust the value of variables in-game (e.g. tuning jump height or walk speed), but the current way I’m doing it is overly cumbersome and inflexible.

Then look at using WPF for your editor

You can use code behind to bind variables directly to UI elements

In your code you do things like this

public class BodyAeroData
{
    public Vector3 radiatorRange { get; set; }
    public Vector3 bodyAft { get; set; }
}

Then in the yaml

<Label Content="radiatorRange" Grid.Row="0" Grid.Column="0" Foreground="White"/>
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Path=radiatorRange.X, StringFormat={}{0}, Mode=TwoWay}" Background="Black" Foreground="White"/>
<TextBox Grid.Row="0" Grid.Column="2" Text="{Binding Path=radiatorRange.Y, StringFormat={}{0}, Mode=TwoWay}" Background="Black" Foreground="White"/>
<TextBox Grid.Row="0" Grid.Column="3" Text="{Binding Path=radiatorRange.Z, StringFormat={}{0}, Mode=TwoWay}" Background="Black" Foreground="White"/>

Then when you change something in the UI, the value in C# gets changed automatically

You can pass value types as references to methods if explicitly request it.

        public void IncrementStuff(ref int stuff) => stuff++;
        var stuff = 5;
        IncrementStuff(ref stuff); // Now stuff is 6

EDIT: ref keyword - C# Reference | Microsoft Docs

It has crossed my mind to do something like this, but I’d like to keep my editor system within my main code, and not rely on forms. I also don’t know how to integrate a Monogame game into a WPF. It doesn’t mean I’ve ruled it out though.

I wonder if nullable works here? It’s basically a wrapper class built into the c# syntax

int? TestNullable { get; set; }

Another member of the community pointed me to something similar. More specifically, ref returns and ref locals. So it would look more like:

public int mainStuff = 5;

public ref int GetStuff() { return ref mainStuff; }

    ref int stuff = ref GetStuff();
    stuff++; //mainStuff now equals 5

What do you mean by this?

Another member of the community pointed me to something similar. More specifically, ref returns and ref locals.

I didn’t know you could do that, looks really convoluted though. Why can’t you use wrapper class again?

I’m sorry what are you not getting? It is exactly like I showed you

I mean what are suggesting I use nullable value-types for?

Im a little confused by this. If your making an editor you must built some kind of ui system. Make a textbox where its value is whatever object you want (in this case an int) selecting something in your game changes tbis value to whatever properties you want it to, and changing this value updates whatever value is on your selected object.

There is no data binding on monogames ui controls, because there’s no inbuilt monogame ui controls. You can either use someone else’s library or make your own.

This looks like a use case for dependency injection also known as inversion of control.

This is basically passing a class that handles the parameters you want to change into the classes that use them.

Something like this:

// Interface class defining the parameters that are configurable
public interface IParametersHandler
{
    float JumpHeight { get; set; }
} 

// IParameters implementation that you can change from your editor
public class MyParameters : IParametersHandler
{
    public float JumpHeight { get; set; }
}

// your UI class that gets 'injected' with the parameters when created
class MyJumper
{
     private IParametersHandler _parameters;
    
    class MyJumper(IParametersHandler parameters)
    {
        _parameters = parameters;
    }
       
    // using the 'injected' value
    public void DoSomething()
    {
          float jumpMax = _parameters.JumpHeight;
    }
}
...

Now the 'control has been inverted' i.e. the UI class no longer has control of the jump height etc
1 Like

This is a c# question the simple answer here directly to the question is No.
Value types are pass by value.

Di and other tricks are standardized patterns and ways to do as you alluded to in the second option, Wrap the value type in a class type and then link those references to get at the wrapped value.

For example.
Directly without the interface that uses the di pattern.

public class MyGuy2
{
    public string Name { get; set; }
}
public class MyUi2
{
    MyGuy2 guy2objref;

    public MyUi2(MyGuy2 objref)
    {
        guy2objref = objref;
    }
    public string GetParameter()
    {
        return guy2objref.Name;
    }
    public void SetParameter(string name)
    {
        guy2objref.Name = name;
    }
}

public class TestClass
{

    public void TestRegularRefenceLinking()
    {
        Console.WriteLine("We set up the guy and name him.");
        MyGuy2 guy2 = new MyGuy2();
        guy2.Name = "Bob";
        Console.WriteLine(guy2.Name);

        Console.WriteLine("We set up the ui inject the guy.");
        MyUi2 ui = new MyUi2(guy2);
        Console.WriteLine(ui.GetParameter());

        Console.WriteLine("We rename the parameter in the ui.");
        ui.SetParameter("Fred");
        Console.WriteLine(ui.GetParameter());

        Console.WriteLine("How about the change in guy.");
        Console.WriteLine(guy2.Name);

        Console.WriteLine("How about renaming guy bill and then looking to the ui value.");
        guy2.Name = "Bill";
        Console.WriteLine(ui.GetParameter());
    }
}

The output and result is the same as di without being as generic.
This test result is the same for a int instead of a string.

This breaks down to this basically.

public class MyGuy
{
    public string Name { get; set; }
}
public class MyGuy2
{
    public MyGuy myguyobjref;

    public MyGuy2(MyGuy objref)
    {
        myguyobjref = objref;
    }
}

I know you don’t want to box your variables but you can have them only boxed in the editor like so. The editor calls a function to ask what properties the class has and it returns:

new Properties.Integer(delegate { return Price; }, x => Price = x)

and which calls

public Integer(Func<int> getter, Action<int> setter)
{
    store the getter and setter here for use by the editor
}

I ended up going with delegate ref return calls to do this.

// Class variables
public delegate ref int D_int();
D_int linked_value;
int editor_value;
MyReferencedClass myReferencedClass; // class ref that I wish to view in editor

// Method
ref return int ID() { return ref myReferencedClass.id; }

// Constructor
linked_value = method; // method is a parameter, and is ID in this example

// Update
ref int newValue = ref linked_value();
if (editor_value != newValue)
{
    editor_value = newValue;
    Update_stringBuilder;
}

I also used reflection to generate the variable name for my string label, so I didn’t have to type it twice when I create the object.

string var_label = linked_value.Method.Name;

These work pretty well, and easy to keep separate from my gameplay code.

I also liked the interface idea from jonathanmcc. I could think of some uses for that elsewhere in my code.