我在使用lambda表达式设置结构中的值时遇到问题,该表达式引用了定义lambda表达式的函数中的本地值。如果我理解正确,结构在lambda函数中通过值传递,但我希望它通过引用传递。我不知道怎么做。
测试代码:
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();
}
}
注意: 结构由其他人编写(并用于互操作),我不能将它们更改为类。我喜欢我当前的设计,所以我希望有一种方法来保持这种设计,但只是让Action中的结构表现为一个类。不改变类的另一个原因是某些结构嵌套得很深,并且需要更多的努力来更新,而不是我认为应该是必要的。
答案 0 :(得分:6)
如果您想通过引用传递结构,那么您需要具有ref
参数的自己的委托类型(不在标准Action<>
和Func<>
的集合中)。
此外,使用lambdas时,编译器无法推断ref
和out
参数的类型,因此,您必须明确声明它们或使用良好的旧匿名委托语法(看起来非常类似于声明类型的lambda:)
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);
}
答案 1 :(得分:2)
将结构放在holder类中,并传递holder类的实例。
public class SomeStructHolder
{
public someStruct theStruct;
}