Pass by reference, in a method, in a lambda expression
Hi! I have a bit of an issue.
I want to have a method, to create a slider runtime, which sets a referenced value to the slider value.
To do so, I have created a method:
void CreateSliders(GameObject go)
{
GameObject temp = Instantiate(go, holder);
temp.GetComponentInChildren<Slider>().onValueChanged.AddListener((float f) => SaveChange(f));
}
Now this give me a nice function which should ideally be able to set a referenced value to f, in SaveChange.
Now it looks like this:
public string s = "0";
void Awake()
{
CreateSliders(sliderFab, ref s);
}
void CreateSliders(GameObject go, ref string s)
{
GameObject temp = Instantiate(go, holder);
temp.GetComponentInChildren<Slider>().onValueChanged.AddListener((float f) => SaveChange(f, ref s));
}
void SaveChange(float f, ref string s)
{
s = f.ToString();
}
However, this bit of code is illegal, due to the use of s inside the lambda expression. I have tried a lot of things to solve this issue. If I specify the variable inside the function like so:
public string specified = "0";
void CreateSliders(GameObject go)
{
GameObject temp = Instantiate(go, holder);
temp.GetComponentInChildren<Slider>().onValueChanged.AddListener((float f) => SaveChange(f, ref specified));
}
void SaveChange(float f, ref string s)
{
s = f.ToString();
}
it works as expected. But then it loses the point, as I would need to specify the referenced variable inside every method. Is there any way to pass a reference to the CreateSlider function, which can be used inside the SaveChange function?
Answer by Bir3D · Aug 31, 2019 at 11:39 AM
So, after more research I found a work around. Instead of trying to use the ref keyword, I wrapped it in a class, which by default passes by reference, and which a lambda expression has no issue with.
Given in my original code (not exactly like the one shown above) I was already passing a struct, it was quite simple case of adding a new wrapper, and creating a new one inside the struct. this is the final code:
public class UIPassByReferenceTest : MonoBehaviour
{
public Transform holder;
public GameObject sliderFab, buttonFab;
public Text t1, t2;
public class wrapper
{
public int i;
public float f;
public string s;
public bool b;
}
public struct pref
{
public wrapper wrap;
public pref(wrapper wrap)
{
this.wrap = new wrapper();
}
}
wrapper wrap;
pref a, b;
void Awake()
{
a = new pref(wrap);
b = new pref(wrap);
CreateSliders(sliderFab, a);
CreateSliders(sliderFab, b);
}
void CreateSliders(GameObject go, pref s)
{
GameObject temp = Instantiate(go, holder);
temp.GetComponentInChildren<Slider>().onValueChanged.AddListener((float f) => SaveChange(f, ref s));
}
void SaveChange(float f, ref pref s)
{
s.wrap.s = f.ToString();
}
private void Update()
{
t1.text = a.wrap.s;
t2.text = b.wrap.s;
}
}
And here is how it looks in action
Your answer
Follow this Question
Related Questions
Replace C# Lambda Operator 1 Answer
Trigger events from different sources 0 Answers
Removing items from list by OnTriggerExit 2 Answers
How to make FunRace3D Style Player-Target Distance with UI 0 Answers
Raycast only occurs on start 2 Answers