Reputation: 3506
How I can to pass a reference as a parameter to Async method in Windows Store App ?
I'm looking for something like this:
var a = DoThis(ref obj.value);
public async Task DoThis(ref int value)
{
value = 10;
}
But error:
Async methods cannot have ref or out parameters
Has any another way?
Note:
I need to pass exactly obj.value. This method would be used by different types of objects, by same type of objects, by one object, but I will pass obj.val_1, obj.val_2 or obj.val_10. All values will be same type (for ex string)
Upvotes: 8
Views: 17261
Reputation: 3972
If you don't care about a little overhead and possibly prolonged lifetime of your objects, you could emulate the ref behavior by passing a setter and a getter method to the function, like this:
public async Task DoStuff(Func<int> getter, Action<int> setter)
{
var value1 = getter();
await DoSomeOtherAsyncStuff();
setter(value1 * value1);
}
And call it like this:
await DoStuff(() => obj.Value, x => obj.Value = x);
Upvotes: 21
Reputation: 10349
You can always use the Task<>
class and return the desired value. Then Your code would look something like:
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;
}
EDIT
Ok, the other way to go with this that I can think of is encapsulating the update of the given object's member in a method and then passing an action invoking this method as the task's argument, like so:
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;
}
As far as I tested it the change was made in the child thread, but still it's effect was visible in the parent thread. Hope this helps You.
Upvotes: 4
Reputation: 8471
You can't do this as you have it (as you know). So, a few work arounds:
You can do this by passing the initial object since it will be a reference type
var a = DoThis(obj);
public async Task DoThis(object obj) //replace the object with the actual object type
{
obj.value = 10;
}
EDIT
Based upon your comments, create an interface and have your classes implement it (providing it's always the same type you want to pass). Then you can pass the interface which is shared (maybe over kill, depends on your needs, or even unrealistic amount of work).
Or, provide a base class with the property! (I don't like this suggestion but since you're asking for something which can't be done it may suffice although I don't recommend it).
An example of the interface is here (not using what you have, but close enough using a Colsone App)
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; }
}
}
EDIT2
After next comments, you will have to still use an interface, but re assign the value afterwards. I'm sure there is a better way to do this, but this works:
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; }
}
}
Upvotes: 3
Reputation: 1039438
You could directly pass the object itself and set the value of the corresponding property inside the method:
var a = DoThis(obj);
public async Task DoThis(SomeObject o)
{
o.value = 10;
}
And if you do not have such object simply write one and have the async method take that object as parameter:
public class SomeObject
{
public int Value { get; set; }
}
Upvotes: 13