C# lambda表达式中的结构引用

C# lambda表达式中的结构引用,c#,lambda,struct,C#,Lambda,Struct,在定义lambda表达式的函数中,使用引用本地值的lambda表达式设置结构中的值时遇到问题。如果我理解正确的话,结构是通过lambda函数中的值传递的,但是我希望它通过引用传递。我不知道怎么做 测试代码: public struct partialData { public int foo; } public struct futureData { public int bar; } // if you change this to a class, everything w

在定义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();
    }
}
公共结构部分数据
{
公众谘询委员会;;
}
公共结构未来数据
{
公共酒吧;
}
//如果您将其更改为一个类,那么一切都会按预期工作。
公共结构someStruct
{
公共部分数据pd;
公共未来数据fd;
}
苹果类
{
私人行动托贝赛;
public someStruct makeStruct(partialData pd)
{
someStruct ss=新的someStruct();
ss.pd=pd;
toBeSet=新动作(
(futureValue)=>ss.fd=(futureData)futureValue
);
返回ss;
}
public void futureSet(futureData fd)
{
toBeSet.Invoke(fd);
}
}
班级计划
{
静态void Main(字符串[]参数)
{
部分数据pd;
pd.foo=1;
未来数据fd;
fd.bar=2;
苹果ap=新苹果();
someStruct ss=ap.makeStruct(pd);
ap.futureSet(fd);
//我希望它是1,2,结果是1,0
Console.WriteLine(“foo是:+ss.pd.foo+”,bar是:+ss.fd.bar);
Console.In.ReadLine();
}
}
注:
这些结构是由其他人编写的(用于互操作),我无法将它们更改为类。我喜欢我目前的设计,所以我希望有一种方法可以保持这种设计,但只是让动作中的结构像类一样工作。不更改为类的另一个原因是,某些结构嵌套得很深,更新起来比我认为必要的还要费劲

将结构放在holder类中,并传递holder类的实例

public class SomeStructHolder
{
    public someStruct theStruct;
}

如果要通过引用传递结构,则需要使用
ref
参数(不在标准
Action
Func
集合中)来传递自己的委托类型

此外,在使用lambdas时,编译器无法推断
ref
out
参数的类型,因此,必须显式声明它们或使用良好的旧匿名委托语法(这看起来非常类似于具有声明类型的lambdas):


我不认为将它装箱为
对象
类型,然后在lambda中将其重新转换会起作用,是吗?(如果不难看的话)事实上,等一下,你的
makeStruct
方法本质上不会返回你的“someStruct ss”的副本吗?因此,即使可以在方法中声明实际“ss”实例的lambda目标,makeStruct的调用方不会收到副本而不是原始副本吗?(可以用
ref
参数解决)使用ref并没有解决它,但这是一个我没有想到的问题。不过,您不应该使用属性。访问结构的getter总是会返回结构的一个副本,对其fd字段进行修改。回答得好,我只是不想做所有嵌套结构的事情——我认为委托“感觉”就像我正在寻找的答案——解释我为什么改变了被接受的答案。很遗憾,没有真正的语言或框架支持集合将自己暴露在这种方法中。可变结构比可变类更安全,通常比不可变类型更方便,但类似数组的集合允许使用者修改其中包含的结构字段所需的语法非常可怕。顺便说一句,链接的问题不同,因为这与lambda函数无法捕获周围函数的
ref
out
参数有关,而不是对lambda函数自身参数的限制。@supercat:完全不同意可变结构的安全性。我认为,结构必须是不可变的。但是+1关于这个问题,我的回答有点不准确。更新了答案,谢谢@丹尼斯:可以肯定的是,.net对可变结构的支持存在一些问题,但它们比可变类安全得多。在许多情况下,传输数据的理想方式可能是使用可变类构造实例,然后将数据复制到不可变类或构造不可变包装器。不幸的是,没有方便的方法来创建具有相同属性的并行可变和不可变类。具有公开可变字段的结构几乎同样好,因为保护结构的存储位置不受突变的影响将保护该结构的字段。
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);
}