I'm having trouble setting the values in a struct using a lambda expression referencing local values in the function in which the lambda expression is defined. If I understand it correctly, the struct is passed by value in the lambda function, but I'd like it to pass by reference. I do not know how to do it.
Test code:
public struct partialData
{
public int foo;
}
public struct futureData
{
public int bar;
}
// if you change this to a class, everything works as desired.
public struct someStruct
{
public partialData pd;
public futureData fd;
}
class Apple
{
private Action<object> toBeSet;
public someStruct makeStruct(partialData pd)
{
someStruct ss = new someStruct();
ss.pd = pd;
toBeSet = new Action<object>(
(futureValue) => ss.fd = (futureData)futureValue
);
return ss;
}
public void futureSet(futureData fd)
{
toBeSet.Invoke(fd);
}
}
class Program
{
static void Main(string[] args)
{
partialData pd;
pd.foo = 1;
futureData fd;
fd.bar = 2;
Apple ap=new Apple();
someStruct ss= ap.makeStruct(pd);
ap.futureSet(fd);
// I'd like it to be 1,2, it results in 1,0
Console.WriteLine("foo is: "+ss.pd.foo + ", bar is: "+ss.fd.bar);
Console.In.ReadLine();
}
}
Notes: The structures are written by someone else (and are used for interop), I cannot change them to classes. I like my current design, so I'm hoping for a way to keep this design but just have the struct in the Action behave as a class. Another reason to not change to classes is that some of the structs are nested deeply and would take more effort to update than I think should be necessary.
If you want to pass structure by reference, then you need your own delegate type with ref parameter (which is not in the set of standard Action<> and Func<>).
Also, when using lambdas, compiler can't infer types of ref and out parameters, so, you have to declare them explicitly or use good old anonymous delegates syntax (which looks very similar to lambdas with declared types):
struct S
{
public int f;
}
delegate void DoDelegate(ref S s);
public static void M()
{
var s = new S();
DoDelegate delegate2 = (ref S st) => st.f = 5;
DoDelegate delegate1 = delegate(ref S st) { st.f = 10; };
delegate1.Invoke(ref s);
delegate2.Invoke(ref s);
}
Put the struct in a holder class and pass around an instance of the holder class.
public class SomeStructHolder
{
public someStruct theStruct;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With