【问题标题】:How can I set the value of a parameter that is not passed by reference in an Action<string, int>?如何在 Action<string, int> 中设置未通过引用传递的参数的值?
【发布时间】:2013-09-24 21:34:17
【问题描述】:

我有一个Action&lt;object, object&gt; 的列表,我最终会在某个时间点将其恢复为Action&lt;string, int&gt;,或任何其他两种类型。它表示从一种类型到另一种类型的动态引用映射。由于各种原因,我无法使用ref 或Func&lt;..&gt;。

基本上问题在于,在Action&lt;string, int&gt; 的回调代码中,我需要一种方法来设置传入的int 的值,比如在我将其从字符串转换之后。虽然不是ref,但具体怎么做就不清楚了。

是否有人碰巧知道是否有一种方法可以动态重写该方法,或者以其他方式获取传递给它的值(也许是在堆栈上)并设置int 值...在 CLR 上一步调用栈?

为了阻止任何人说“为什么不改变你的整个程序”或“你什么时候需要这个?”,我只是在尝试一种新的对象映射库的想法。

【问题讨论】:

  • 你不会,如果不是ref 你不能改变调用者的值。您可以返回允许调用者更改它的新值,但是除非传递了引用,否则每个具有的 int 版本是不同的并且是隔离的。
  • 其实,你可以改变调用者的值。您可以在运行时重写该方法以由 ref 传递,但这不是一个很好的解决方案,我正在尝试提出一个更好的解决方案。

标签: c# reflection dynamic-programming


【解决方案1】:

值类型不可能。它们总是被复制到堆栈上,并且在装箱的情况下(对于遇到的每个装箱)它们被移动到堆中的新位置并传回一个引用。

您可以尝试将您的 int 包装成一个引用类型并利用副作用(因为这正是您想要做的。或者您可以保留 int 参数并将结果存储在一个封闭的变量中。例如: (string str, int i) =&gt; { myDictionary.Add(str, i); }.

【讨论】:

  • 值类型并不总是复制到堆栈上,所以我很难相信根据您所写的内容这是不可能的。但是,我正在考虑在运行时反映调用者和被调用者 CIL,以便做我想做的事情并通过以某种方式使用堆栈来访问该盒装引用。
  • 这不是真的。如果参数有 ref 修饰符,那么它不会被复制,它只是别名。问题变成了如何将ref 修饰符添加到委托。 如果您添加了不能修改委托以使用ref参数的约束,那么这个答案是正确的,您需要包装该值输入引用类型。
  • 确实如此,只有当参数通过引用传递时,值才不会被复制而是被引用。但是 Action 委托在任何定义上都没有任何 ref 修饰符。细化“玩堆栈”
【解决方案2】:

有趣的问题,我很想知道根本答案!

到目前为止,我最好的方法是创建自己的委托,并将它们包装在泛型中

delegate void MyAction<T,T1>(ref T a, T1 b);
static void Main(string[] args)
    {
        MyAction<string, int> action = Foo;            
        var arr = new object[] { "", 5 };
        action.DynamicInvoke(arr);
    }

    private static void Foo(ref string a, int b)
    {
        a = b.ToString();
    }

【讨论】:

  • 所以这个问题是Action&lt;string, int&gt; 不能改变。如果我将它包装在 Action&lt;string, ref int&gt; 中,那么它会向上传递一层,而不是两层,如果它被包裹,那就是它需要到达的地方。如果它没有被包装,它只需要再传递一个级别。
  • 是的,这只是一种变通方法,并不能解决您以某种方式侵入 IL 代码的根本问题。 PS:你说的两个层次是什么意思?
  • 我的意思是当你在一个方法中调用一个方法时,你最终会得到两个堆栈深度,所以如果想法是将一个方法包装在另一个方法中并让最里面的方法暴露一个 @987654324 @ 参数,那么您仍然需要获取该 ref 参数并将其传递回堆栈并以某种方式侵入 IL,但现在它将是堆栈的两层而不是一层。每个嵌套方法调用或调用都会导致堆栈“框架”深度增加(没有优化)。但是,是的,不幸的是,这个应用程序无法直接使用ref。
猜你喜欢
  • 2012-04-14
  • 1970-01-01
  • 1970-01-01
  • 2011-06-25
  • 2015-07-06
  • 1970-01-01
  • 2012-02-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多