6

如何将引用作为参数传递给 Windows Store App 中的 Async 方法?
我正在寻找这样的东西:

var a = DoThis(ref obj.value);

public async Task DoThis(ref int value)
{
    value = 10;
}

但是错误:

异步方法不能有 ref 或 out 参数

有没有别的办法?

注意:
我需要准确传递 obj.value。此方法将被不同类型的对象、相同类型的对象、一个对象使用,但我将传递 obj.val_1、obj.val_2 或 obj.val_10。所有值都将是相同的类型(例如字符串)

4

4 回答 4

12

如果您不关心对象的一点开销和可能延长的生命周期,您可以通过将 setter 和 getter 方法传递给函数来模拟 ref 行为,如下所示:

public async Task DoStuff(Func<int> getter, Action<int> setter)
{
    var value1 = getter();
    await DoSomeOtherAsyncStuff();
    setter(value1 * value1);
}

并这样称呼它:

await DoStuff(() => obj.Value, x => obj.Value = x);
于 2013-05-21T09:13:17.460 回答
7

您可以直接传递对象本身并在方法内设置相应属性的值:

var a = DoThis(obj);

public async Task DoThis(SomeObject o)
{
    o.value = 10;
}

如果您没有这样的对象,只需编写一个并让异步方法将该对象作为参数:

public class SomeObject
{
    public int Value { get; set; }
}
于 2013-05-21T07:57:14.910 回答
2

您始终可以使用Task<>该类并返回所需的值。然后你的代码看起来像:

var a = DoThis(obj.value);
obj.value = a.Result;

public async Task<int> DoThis(int value)
{
    int result = value + 10; //compute the resulting value
    return result;
}

编辑

好的,我能想到的另一种方法是将给定对象成员的更新封装在一个方法中,然后传递一个调用该方法的动作作为任务的参数,如下所示:

var a = DoThis(() => ChangeValue(ref obj.value));

public void ChangeValue(ref int val)
{
    val = 10;
}

public async Task DoThis(Action act)
{
    var t = new Task(act);
    t.Start();
    await t;
}

据我测试,更改是在子线程中进行的,但它的效果在父线程中仍然可见。希望这对您有所帮助。

于 2013-05-21T08:20:14.183 回答
1

你不能这样做(如你所知)。因此,一些解决方法:

您可以通过传递初始对象来做到这一点,因为它将是一个引用类型

var a = DoThis(obj);  

public async Task DoThis(object obj) //replace the object with the actual object type
{
    obj.value = 10;
}

编辑

根据您的评论,创建一个接口并让您的类实现它(假设它始终是您想要传递的相同类型)。然后您可以传递共享的界面(可能过度杀死,取决于您的需求,甚至是不切实际的工作量)。

或者,提供具有该属性的基类!(我不喜欢这个建议,但既然你要求的是一些无法完成的事情,尽管我不推荐它,但它可能就足够了)。

界面示例在这里(不使用您拥有的,但使用 Colsone 应用程序足够接近)

using System;

namespace InterfacesReferenceTypes
{
    class Program
    {
        static void Main(string[] args)
        {
            MyClass mc = new MyClass();
            DoThis(mc);
            Console.WriteLine(mc.Number);
            Console.ReadKey();
        }

        static void DoThis(IDemo id)
        {
            id.Number = 10;
        }
     }

    class MyClass : IDemo
    {
        //other props and methods etc
        public int Number { get; set; }
    }

    interface IDemo
    {
        int Number { get; set; }
    }
}

编辑2

在下一个评论之后,您仍必须使用接口,但之后重新分配值。我确信有更好的方法可以做到这一点,但这有效:

using System.Text;

namespace InterfacesRerefenceTypes
{
    class Program
    {
        static void Main(string[] args)
        {
            MyClass mc = new MyClass();
            Console.WriteLine(mc.Number);
            mc.val1 = 3;
            mc.val2 = 5;
            mc.Number = mc.val2;
            DoThis(mc);
            mc.val2 = mc.Number;

            Console.WriteLine(mc.val2);
            Console.ReadKey();
        }

        static void DoThis(IDemo id)
        {
            id.Number = 15;
        }
    }

    class MyClass : IDemo
    {
        public int val1 { get; set; }
        public int val2 { get; set; }
        public int Number { get; set; }
    }

    interface IDemo
    {
        int Number { get; set; }
    }
}
于 2013-05-21T07:58:17.410 回答