Related
I have a function that takes a list of Func<bool> each with an attached value. It iterates the list and returns the attached value if a delegate returns true. Some of these delegates call the same function with the same parameters how do I best memoize the result of such calls within the scope of the TryFindValue method?
The return value of the functions may change between calls to TryFindValue, but they will not change while iterating the list. I would like to avoid generating garbage (boxing/unboxing by casting to object for example). Ideally, I would only have to use the space for memoized values in the scope of TryFindValue and not for the entire lifetime of each delegate for example, but I do not know if that is possible.
public class SomeClass
{
public bool TryFindValue(List<CondValue> list, out int value)
{
for (int i = 0; i < list.Count; i++)
{
var condValue = list[i];
if (condValue.cond())
{
value = condValue.value;
return true;
}
}
value = default(int);
return false;
}
}
public class SomeOtherClass
{
private List<CondValue> list;
public SomeOtherClass()
{
list = new List<CondValue>();
// SomeMethod(3) will be calculated twice
list.Add(new CondValue(() => SomeMethod(3) > SomeOtherMethod(), 42));
list.Add(new CondValue(() => SomeMethod(3) < SomeThirdMethod(), 35));
}
private float SomeMethod(int value)
{
// Implementation... (uses some internal or global state)
}
private int SomeOtherMethod()
{
// Implementation... (uses some internal or global state)
}
private int SomeThirdMethod()
{
// Implementation... (uses some internal or global state)
}
}
public struct CondValue
{
public Func<bool> cond;
public int value;
public CondValue(Func<bool> func, int value)
{
this.func = func;
this.value = value;
}
}
If you turn CondValue.cond into an expression tree instead of a Func then maybe you could make some complicated solution. I have no experience doing so and I wouldn't suggest venturing out on that adventure. Apart from that I don't see a good solution to only keep it cached/memorized within the lifetime of a single call to TryFindValue.
I would rather ask you:
Is there any good reason you have the current setup?
It seems like an unnecessarily complicated setup. Since you've only shown a very abstract example it's difficult to suggest a better alternative.
Would e.g. SomeMethod(3) not always return the same value?
You could wrap that method in some caching logic (e.g. with help from PostSharp). But if it doesn't consistently return the same value, you'd have to clear that cache when necessary, which makes it harder to maintain.
Instead of having individual conditions that return true or false with an attached value you could just return the value or null. How does that help? For the following solution, I am assuming that the delegates in the list that call the same function are added to the list together in the same function (here in the constructor SomeOtherClass). From there you could batch together delegates that call the same functions with the same parameters in an if-else if code block and manually "memoize" the result of the function at the top of the delegate.
Delegates that call the same functions with the same parameters smells like they are related in this if-else if relationship anyway. I have added SomeFourthMethod to show how to still compactly add a single conditional individually.
If you have suggestions to improve the details of this solution (using something else than nullable, etc.) then feel free to suggest it in a comment.
If all the conditions are always independent and just happen to sometimes call the same function, then this solution might not be appropriate. Otherwise, it is the simplest most effective solution I can think of.
public class SomeClass
{
public bool TryFindValue(List<Func<int?>> list, out int value)
{
for (int i = 0; i < list.Count; i++)
{
var func = list[i];
int? ret = func();
if (ret.HasValue)
{
value = ret.Value;
return true;
}
}
value = default(int);
return false;
}
}
public class SomeOtherClass
{
private List<Func<int?>> list;
public SomeOtherClass()
{
list = new List<Func<int?>>();
Add(() =>
{
float memoized = SomeMethod(3);
if (memoized > SomeOtherMethod())
return 42;
else if (memoized < SomeThirdMethod())
return 35;
return null;
});
Add(() => SomeFourthMethod() > 4, 72);
}
private void Add(Func<int?> snippet)
{
list.Add(snippet);
}
private void Add(Func<bool> cond, int value)
{
list.Add(() =>
{
if (cond())
return value;
return null;
});
}
private float SomeMethod(int value)
{
// Implementation... (uses some internal or global state)
}
private int SomeOtherMethod()
{
// Implementation... (uses some internal or global state)
}
private int SomeThirdMethod()
{
// Implementation... (uses some internal or global state)
}
private int SomeFourthMethod()
{
// Implementation... (uses some internal or global state)
}
}
I want to write an async method with an out parameter, like this:
public async void Method1()
{
int op;
int result = await GetDataTaskAsync(out op);
}
How do I do this in GetDataTaskAsync?
You can't have async methods with ref or out parameters.
Lucian Wischik explains why this is not possible on this MSDN thread: http://social.msdn.microsoft.com/Forums/en-US/d2f48a52-e35a-4948-844d-828a1a6deb74/why-async-methods-cannot-have-ref-or-out-parameters
As for why async methods don't support out-by-reference parameters?
(or ref parameters?) That's a limitation of the CLR. We chose to
implement async methods in a similar way to iterator methods -- i.e.
through the compiler transforming the method into a
state-machine-object. The CLR has no safe way to store the address of
an "out parameter" or "reference parameter" as a field of an object.
The only way to have supported out-by-reference parameters would be if
the async feature were done by a low-level CLR rewrite instead of a
compiler-rewrite. We examined that approach, and it had a lot going
for it, but it would ultimately have been so costly that it'd never
have happened.
A typical workaround for this situation is to have the async method return a Tuple instead.
You could re-write your method as such:
public async Task Method1()
{
var tuple = await GetDataTaskAsync();
int op = tuple.Item1;
int result = tuple.Item2;
}
public async Task<Tuple<int, int>> GetDataTaskAsync()
{
//...
return new Tuple<int, int>(1, 2);
}
The C#7+ Solution is to use implicit tuple syntax.
private async Task<(bool IsSuccess, IActionResult Result)> TryLogin(OpenIdConnectRequest request)
{
return (true, BadRequest(new OpenIdErrorResponse
{
Error = OpenIdConnectConstants.Errors.AccessDenied,
ErrorDescription = "Access token provided is not valid."
}));
}
return result utilizes the method signature defined property names. e.g:
var foo = await TryLogin(request);
if (foo.IsSuccess)
return foo.Result;
You cannot have ref or out parameters in async methods (as was already noted).
This screams for some modelling in the data moving around:
public class Data
{
public int Op {get; set;}
public int Result {get; set;}
}
public async void Method1()
{
Data data = await GetDataTaskAsync();
// use data.Op and data.Result from here on
}
public async Task<Data> GetDataTaskAsync()
{
var returnValue = new Data();
// Fill up returnValue
return returnValue;
}
You gain the ability to reuse your code more easily, plus it's way more readable than variables or tuples.
I had the same problem as I like using the Try-method-pattern which basically seems to be incompatible to the async-await-paradigm...
Important to me is that I can call the Try-method within a single if-clause and do not have to pre-define the out-variables before, but can do it in-line like in the following example:
if (TryReceive(out string msg))
{
// use msg
}
So I came up with the following solutions:
Note: The new solution is superior, because it can be used with methods that simply return a tuple as described in many of the other answers here, what might often be found in existing code!
New solution:
Create extension methods for ValueTuples:
public static class TupleExtensions
{
public static bool TryOut<P2>(this ValueTuple<bool, P2> tuple, out P2 p2)
{
bool p1;
(p1, p2) = tuple;
return p1;
}
public static bool TryOut<P2, P3>(this ValueTuple<bool, P2, P3> tuple, out P2 p2, out P3 p3)
{
bool p1;
(p1, p2, p3) = tuple;
return p1;
}
// continue to support larger tuples...
}
Define async Try-method like this:
public async Task<(bool, string)> TryReceiveAsync()
{
string message;
bool success;
// ...
return (success, message);
}
Call the async Try-method like this:
if ((await TryReceiveAsync()).TryOut(out string msg))
{
// use msg
}
Old solution:
Define a helper struct:
public struct AsyncOut<T, OUT>
{
private readonly T returnValue;
private readonly OUT result;
public AsyncOut(T returnValue, OUT result)
{
this.returnValue = returnValue;
this.result = result;
}
public T Out(out OUT result)
{
result = this.result;
return returnValue;
}
public T ReturnValue => returnValue;
public static implicit operator AsyncOut<T, OUT>((T returnValue ,OUT result) tuple) =>
new AsyncOut<T, OUT>(tuple.returnValue, tuple.result);
}
Define async Try-method like this:
public async Task<AsyncOut<bool, string>> TryReceiveAsync()
{
string message;
bool success;
// ...
return (success, message);
}
Call the async Try-method like this:
if ((await TryReceiveAsync()).Out(out string msg))
{
// use msg
}
For multiple out parameters you can define additional structs (e.g. AsyncOut<T,OUT1, OUT2>) or you can return a tuple.
Alex made a great point on readability. Equivalently, a function is also interface enough to define the type(s) being returned and you also get meaningful variable names.
delegate void OpDelegate(int op);
Task<bool> GetDataTaskAsync(OpDelegate callback)
{
bool canGetData = true;
if (canGetData) callback(5);
return Task.FromResult(canGetData);
}
Callers provide a lambda (or a named function) and intellisense helps by copying the variable name(s) from the delegate.
int myOp;
bool result = await GetDataTaskAsync(op => myOp = op);
This particular approach is like a "Try" method where myOp is set if the method result is true. Otherwise, you don't care about myOp.
I love the Try pattern. It's a tidy pattern.
if (double.TryParse(name, out var result))
{
// handle success
}
else
{
// handle error
}
But, it's challenging with async. That doesn't mean we don't have real options. Here are the three core approaches you can consider for async methods in a quasi-version of the Try pattern.
Approach 1 - output a structure
This looks most like a sync Try method only returning a tuple instead of a bool with an out parameter, which we all know is not permitted in C#.
var result = await DoAsync(name);
if (result.Success)
{
// handle success
}
else
{
// handle error
}
With a method that returns true of false and never throws an exception.
Remember, throwing an exception in a Try method breaks the whole purpose of the pattern.
async Task<(bool Success, StorageFile File, Exception exception)> DoAsync(string fileName)
{
try
{
var folder = ApplicationData.Current.LocalCacheFolder;
return (true, await folder.GetFileAsync(fileName), null);
}
catch (Exception exception)
{
return (false, null, exception);
}
}
Approach 2 - pass in callback methods
We can use anonymous methods to set external variables. It's clever syntax, though slightly complicated. In small doses, it's fine.
var file = default(StorageFile);
var exception = default(Exception);
if (await DoAsync(name, x => file = x, x => exception = x))
{
// handle success
}
else
{
// handle failure
}
The method obeys the basics of the Try pattern but sets out parameters to passed in callback methods. It's done like this.
async Task<bool> DoAsync(string fileName, Action<StorageFile> file, Action<Exception> error)
{
try
{
var folder = ApplicationData.Current.LocalCacheFolder;
file?.Invoke(await folder.GetFileAsync(fileName));
return true;
}
catch (Exception exception)
{
error?.Invoke(exception);
return false;
}
}
There's a question in my mind about performance here. But, the C# compiler is so freaking smart, that I think you're safe choosing this option, almost for sure.
Approach 3 - use ContinueWith
What if you just use the TPL as designed? No tuples. The idea here is that we use exceptions to redirect ContinueWith to two different paths.
await DoAsync(name).ContinueWith(task =>
{
if (task.Exception != null)
{
// handle fail
}
if (task.Result is StorageFile sf)
{
// handle success
}
});
With a method that throws an exception when there is any kind of failure. That's different than returning a boolean. It's a way to communicate with the TPL.
async Task<StorageFile> DoAsync(string fileName)
{
var folder = ApplicationData.Current.LocalCacheFolder;
return await folder.GetFileAsync(fileName);
}
In the code above, if the file is not found, an exception is thrown. This will invoke the failure ContinueWith that will handle Task.Exception in its logic block. Neat, huh?
Listen, there's a reason we love the Try pattern. It's fundamentally so neat and readable and, as a result, maintainable. As you choose your approach, watchdog for readability. Remember the next developer who in 6 months and doesn't have you to answer clarifying questions. Your code can be the only documentation a developer will ever have.
Best of luck.
One nice feature of out parameters is that they can be used to return data even when a function throws an exception. I think the closest equivalent to doing this with an async method would be using a new object to hold the data that both the async method and caller can refer to. Another way would be to pass a delegate as suggested in another answer.
Note that neither of these techniques will have any of the sort of enforcement from the compiler that out has. I.e., the compiler won’t require you to set the value on the shared object or call a passed in delegate.
Here’s an example implementation using a shared object to imitate ref and out for use with async methods and other various scenarios where ref and out aren’t available:
class Ref<T>
{
// Field rather than a property to support passing to functions
// accepting `ref T` or `out T`.
public T Value;
}
async Task OperationExampleAsync(Ref<int> successfulLoopsRef)
{
var things = new[] { 0, 1, 2, };
var i = 0;
while (true)
{
// Fourth iteration will throw an exception, but we will still have
// communicated data back to the caller via successfulLoopsRef.
things[i] += i;
successfulLoopsRef.Value++;
i++;
}
}
async Task UsageExample()
{
var successCounterRef = new Ref<int>();
// Note that it does not make sense to access successCounterRef
// until OperationExampleAsync completes (either fails or succeeds)
// because there’s no synchronization. Here, I think of passing
// the variable as “temporarily giving ownership” of the referenced
// object to OperationExampleAsync. Deciding on conventions is up to
// you and belongs in documentation ^^.
try
{
await OperationExampleAsync(successCounterRef);
}
finally
{
Console.WriteLine($"Had {successCounterRef.Value} successful loops.");
}
}
Here's the code of #dcastro's answer modified for C# 7.0 with named tuples and tuple deconstruction, which streamlines the notation:
public async void Method1()
{
// Version 1, named tuples:
// just to show how it works
/*
var tuple = await GetDataTaskAsync();
int op = tuple.paramOp;
int result = tuple.paramResult;
*/
// Version 2, tuple deconstruction:
// much shorter, most elegant
(int op, int result) = await GetDataTaskAsync();
}
public async Task<(int paramOp, int paramResult)> GetDataTaskAsync()
{
//...
return (1, 2);
}
For details about the new named tuples, tuple literals and tuple deconstructions see:
https://blogs.msdn.microsoft.com/dotnet/2017/03/09/new-features-in-c-7-0/
The limitation of the async methods not accepting out parameters applies only to the compiler-generated async methods, these declared with the async keyword. It doesn't apply to hand-crafted async methods. In other words it is possible to create Task returning methods accepting out parameters. For example lets say that we already have a ParseIntAsync method that throws, and we want to create a TryParseIntAsync that doesn't throw. We could implement it like this:
public static Task<bool> TryParseIntAsync(string s, out Task<int> result)
{
var tcs = new TaskCompletionSource<int>();
result = tcs.Task;
return ParseIntAsync(s).ContinueWith(t =>
{
if (t.IsFaulted)
{
tcs.SetException(t.Exception.InnerException);
return false;
}
tcs.SetResult(t.Result);
return true;
}, default, TaskContinuationOptions.None, TaskScheduler.Default);
}
Using the TaskCompletionSource and the ContinueWith method is a bit awkward, but there is no other option since we can't use the convenient await keyword inside this method.
Usage example:
if (await TryParseIntAsync("-13", out var result))
{
Console.WriteLine($"Result: {await result}");
}
else
{
Console.WriteLine($"Parse failed");
}
Update: If the async logic is too complex to be expressed without await, then it could be encapsulated inside a nested asynchronous anonymous delegate. A TaskCompletionSource would still be needed for the out parameter. It is possible that the out parameter could be completed before
the completion of the main task, as in the example bellow:
public static Task<string> GetDataAsync(string url, out Task<int> rawDataLength)
{
var tcs = new TaskCompletionSource<int>();
rawDataLength = tcs.Task;
return ((Func<Task<string>>)(async () =>
{
var response = await GetResponseAsync(url);
var rawData = await GetRawDataAsync(response);
tcs.SetResult(rawData.Length);
return await FilterDataAsync(rawData);
}))();
}
This example assumes the existence of three asynchronous methods GetResponseAsync, GetRawDataAsync and FilterDataAsync that are called
in succession. The out parameter is completed on the completion of the second method. The GetDataAsync method could be used like this:
var data = await GetDataAsync("http://example.com", out var rawDataLength);
Console.WriteLine($"Data: {data}");
Console.WriteLine($"RawDataLength: {await rawDataLength}");
Awaiting the data before awaiting the rawDataLength is important in this simplified example, because in case of an exception the out parameter will never be completed.
I think using ValueTuples like this can work. You have to add the ValueTuple NuGet package first though:
public async void Method1()
{
(int op, int result) tuple = await GetDataTaskAsync();
int op = tuple.op;
int result = tuple.result;
}
public async Task<(int op, int result)> GetDataTaskAsync()
{
int x = 5;
int y = 10;
return (op: x, result: y):
}
Pattern matching to the rescue! C#9 (I think) onwards:
// example of a method that would traditionally would use an out parameter
public async Task<(bool success, int? value)> TryGetAsync()
{
int? value = // get it from somewhere
return (value.HasValue, value);
}
Use it like this:
if (await TryGetAsync() is (true, int value))
{
Console.WriteLine($"This is the value: {value}");
}
This is very similar to the answer provided by Michael Gehling, but I had my own solution until I found his and noticed that I wasn't the first to think of using an implicit conversion.
Regardless, I wanted to share as mine also supports when nullable is set to enable
public readonly struct TryResult<TOut>
{
#region constructors
public TryResult(bool success, TOut? value) => (Success, Value) = (success, value);
#endregion
#region properties
public bool Success { get; init; }
[MemberNotNullWhen(true, nameof(Success))] public TOut? Value { get; init; }
#endregion
#region methods
public static implicit operator bool(TryResult<TOut> result) => result.Success;
public static implicit operator TryResult<TOut>(TOut value) => new (true, value);
public void Deconstruct(out bool success, out TOut? value) => (success, value) = (Success, Value);
public TryResult<TOut> Out([NotNullWhen(true)] out TOut? value)
{
value = Value;
return this;
}
#endregion
}
Then you can write a Try method like this:
public static async Task<TryResult<byte[]>> TryGetBytesAsync(string file) =>
File.Exists(file)
? await File.ReadAllBytesAsync(file)
: default(TryResult<byte[]>);
And call it like this:
if ((await TryGetBytesAsync(file)).Out(out var bytes))
Console.WriteLine($"File has {bytes.Length} bytes.");
For developers who REALLY want to keep it in parameter, here might be another workaround.
Change the parameter to an array or List to wrap the actual value up. Remember to initialize the list before sending into the method. After returned, be sure to check value existence before consuming it. Code with caution.
You can do this by using TPL (task parallel library) instead of direct using await keyword.
private bool CheckInCategory(int? id, out Category category)
{
if (id == null || id == 0)
category = null;
else
category = Task.Run(async () => await _context.Categories.FindAsync(id ?? 0)).Result;
return category != null;
}
if(!CheckInCategory(int? id, out var category)) return error
I want to write an async method with an out parameter, like this:
public async void Method1()
{
int op;
int result = await GetDataTaskAsync(out op);
}
How do I do this in GetDataTaskAsync?
You can't have async methods with ref or out parameters.
Lucian Wischik explains why this is not possible on this MSDN thread: http://social.msdn.microsoft.com/Forums/en-US/d2f48a52-e35a-4948-844d-828a1a6deb74/why-async-methods-cannot-have-ref-or-out-parameters
As for why async methods don't support out-by-reference parameters?
(or ref parameters?) That's a limitation of the CLR. We chose to
implement async methods in a similar way to iterator methods -- i.e.
through the compiler transforming the method into a
state-machine-object. The CLR has no safe way to store the address of
an "out parameter" or "reference parameter" as a field of an object.
The only way to have supported out-by-reference parameters would be if
the async feature were done by a low-level CLR rewrite instead of a
compiler-rewrite. We examined that approach, and it had a lot going
for it, but it would ultimately have been so costly that it'd never
have happened.
A typical workaround for this situation is to have the async method return a Tuple instead.
You could re-write your method as such:
public async Task Method1()
{
var tuple = await GetDataTaskAsync();
int op = tuple.Item1;
int result = tuple.Item2;
}
public async Task<Tuple<int, int>> GetDataTaskAsync()
{
//...
return new Tuple<int, int>(1, 2);
}
The C#7+ Solution is to use implicit tuple syntax.
private async Task<(bool IsSuccess, IActionResult Result)> TryLogin(OpenIdConnectRequest request)
{
return (true, BadRequest(new OpenIdErrorResponse
{
Error = OpenIdConnectConstants.Errors.AccessDenied,
ErrorDescription = "Access token provided is not valid."
}));
}
return result utilizes the method signature defined property names. e.g:
var foo = await TryLogin(request);
if (foo.IsSuccess)
return foo.Result;
You cannot have ref or out parameters in async methods (as was already noted).
This screams for some modelling in the data moving around:
public class Data
{
public int Op {get; set;}
public int Result {get; set;}
}
public async void Method1()
{
Data data = await GetDataTaskAsync();
// use data.Op and data.Result from here on
}
public async Task<Data> GetDataTaskAsync()
{
var returnValue = new Data();
// Fill up returnValue
return returnValue;
}
You gain the ability to reuse your code more easily, plus it's way more readable than variables or tuples.
I had the same problem as I like using the Try-method-pattern which basically seems to be incompatible to the async-await-paradigm...
Important to me is that I can call the Try-method within a single if-clause and do not have to pre-define the out-variables before, but can do it in-line like in the following example:
if (TryReceive(out string msg))
{
// use msg
}
So I came up with the following solutions:
Note: The new solution is superior, because it can be used with methods that simply return a tuple as described in many of the other answers here, what might often be found in existing code!
New solution:
Create extension methods for ValueTuples:
public static class TupleExtensions
{
public static bool TryOut<P2>(this ValueTuple<bool, P2> tuple, out P2 p2)
{
bool p1;
(p1, p2) = tuple;
return p1;
}
public static bool TryOut<P2, P3>(this ValueTuple<bool, P2, P3> tuple, out P2 p2, out P3 p3)
{
bool p1;
(p1, p2, p3) = tuple;
return p1;
}
// continue to support larger tuples...
}
Define async Try-method like this:
public async Task<(bool, string)> TryReceiveAsync()
{
string message;
bool success;
// ...
return (success, message);
}
Call the async Try-method like this:
if ((await TryReceiveAsync()).TryOut(out string msg))
{
// use msg
}
Old solution:
Define a helper struct:
public struct AsyncOut<T, OUT>
{
private readonly T returnValue;
private readonly OUT result;
public AsyncOut(T returnValue, OUT result)
{
this.returnValue = returnValue;
this.result = result;
}
public T Out(out OUT result)
{
result = this.result;
return returnValue;
}
public T ReturnValue => returnValue;
public static implicit operator AsyncOut<T, OUT>((T returnValue ,OUT result) tuple) =>
new AsyncOut<T, OUT>(tuple.returnValue, tuple.result);
}
Define async Try-method like this:
public async Task<AsyncOut<bool, string>> TryReceiveAsync()
{
string message;
bool success;
// ...
return (success, message);
}
Call the async Try-method like this:
if ((await TryReceiveAsync()).Out(out string msg))
{
// use msg
}
For multiple out parameters you can define additional structs (e.g. AsyncOut<T,OUT1, OUT2>) or you can return a tuple.
Alex made a great point on readability. Equivalently, a function is also interface enough to define the type(s) being returned and you also get meaningful variable names.
delegate void OpDelegate(int op);
Task<bool> GetDataTaskAsync(OpDelegate callback)
{
bool canGetData = true;
if (canGetData) callback(5);
return Task.FromResult(canGetData);
}
Callers provide a lambda (or a named function) and intellisense helps by copying the variable name(s) from the delegate.
int myOp;
bool result = await GetDataTaskAsync(op => myOp = op);
This particular approach is like a "Try" method where myOp is set if the method result is true. Otherwise, you don't care about myOp.
I love the Try pattern. It's a tidy pattern.
if (double.TryParse(name, out var result))
{
// handle success
}
else
{
// handle error
}
But, it's challenging with async. That doesn't mean we don't have real options. Here are the three core approaches you can consider for async methods in a quasi-version of the Try pattern.
Approach 1 - output a structure
This looks most like a sync Try method only returning a tuple instead of a bool with an out parameter, which we all know is not permitted in C#.
var result = await DoAsync(name);
if (result.Success)
{
// handle success
}
else
{
// handle error
}
With a method that returns true of false and never throws an exception.
Remember, throwing an exception in a Try method breaks the whole purpose of the pattern.
async Task<(bool Success, StorageFile File, Exception exception)> DoAsync(string fileName)
{
try
{
var folder = ApplicationData.Current.LocalCacheFolder;
return (true, await folder.GetFileAsync(fileName), null);
}
catch (Exception exception)
{
return (false, null, exception);
}
}
Approach 2 - pass in callback methods
We can use anonymous methods to set external variables. It's clever syntax, though slightly complicated. In small doses, it's fine.
var file = default(StorageFile);
var exception = default(Exception);
if (await DoAsync(name, x => file = x, x => exception = x))
{
// handle success
}
else
{
// handle failure
}
The method obeys the basics of the Try pattern but sets out parameters to passed in callback methods. It's done like this.
async Task<bool> DoAsync(string fileName, Action<StorageFile> file, Action<Exception> error)
{
try
{
var folder = ApplicationData.Current.LocalCacheFolder;
file?.Invoke(await folder.GetFileAsync(fileName));
return true;
}
catch (Exception exception)
{
error?.Invoke(exception);
return false;
}
}
There's a question in my mind about performance here. But, the C# compiler is so freaking smart, that I think you're safe choosing this option, almost for sure.
Approach 3 - use ContinueWith
What if you just use the TPL as designed? No tuples. The idea here is that we use exceptions to redirect ContinueWith to two different paths.
await DoAsync(name).ContinueWith(task =>
{
if (task.Exception != null)
{
// handle fail
}
if (task.Result is StorageFile sf)
{
// handle success
}
});
With a method that throws an exception when there is any kind of failure. That's different than returning a boolean. It's a way to communicate with the TPL.
async Task<StorageFile> DoAsync(string fileName)
{
var folder = ApplicationData.Current.LocalCacheFolder;
return await folder.GetFileAsync(fileName);
}
In the code above, if the file is not found, an exception is thrown. This will invoke the failure ContinueWith that will handle Task.Exception in its logic block. Neat, huh?
Listen, there's a reason we love the Try pattern. It's fundamentally so neat and readable and, as a result, maintainable. As you choose your approach, watchdog for readability. Remember the next developer who in 6 months and doesn't have you to answer clarifying questions. Your code can be the only documentation a developer will ever have.
Best of luck.
One nice feature of out parameters is that they can be used to return data even when a function throws an exception. I think the closest equivalent to doing this with an async method would be using a new object to hold the data that both the async method and caller can refer to. Another way would be to pass a delegate as suggested in another answer.
Note that neither of these techniques will have any of the sort of enforcement from the compiler that out has. I.e., the compiler won’t require you to set the value on the shared object or call a passed in delegate.
Here’s an example implementation using a shared object to imitate ref and out for use with async methods and other various scenarios where ref and out aren’t available:
class Ref<T>
{
// Field rather than a property to support passing to functions
// accepting `ref T` or `out T`.
public T Value;
}
async Task OperationExampleAsync(Ref<int> successfulLoopsRef)
{
var things = new[] { 0, 1, 2, };
var i = 0;
while (true)
{
// Fourth iteration will throw an exception, but we will still have
// communicated data back to the caller via successfulLoopsRef.
things[i] += i;
successfulLoopsRef.Value++;
i++;
}
}
async Task UsageExample()
{
var successCounterRef = new Ref<int>();
// Note that it does not make sense to access successCounterRef
// until OperationExampleAsync completes (either fails or succeeds)
// because there’s no synchronization. Here, I think of passing
// the variable as “temporarily giving ownership” of the referenced
// object to OperationExampleAsync. Deciding on conventions is up to
// you and belongs in documentation ^^.
try
{
await OperationExampleAsync(successCounterRef);
}
finally
{
Console.WriteLine($"Had {successCounterRef.Value} successful loops.");
}
}
Here's the code of #dcastro's answer modified for C# 7.0 with named tuples and tuple deconstruction, which streamlines the notation:
public async void Method1()
{
// Version 1, named tuples:
// just to show how it works
/*
var tuple = await GetDataTaskAsync();
int op = tuple.paramOp;
int result = tuple.paramResult;
*/
// Version 2, tuple deconstruction:
// much shorter, most elegant
(int op, int result) = await GetDataTaskAsync();
}
public async Task<(int paramOp, int paramResult)> GetDataTaskAsync()
{
//...
return (1, 2);
}
For details about the new named tuples, tuple literals and tuple deconstructions see:
https://blogs.msdn.microsoft.com/dotnet/2017/03/09/new-features-in-c-7-0/
The limitation of the async methods not accepting out parameters applies only to the compiler-generated async methods, these declared with the async keyword. It doesn't apply to hand-crafted async methods. In other words it is possible to create Task returning methods accepting out parameters. For example lets say that we already have a ParseIntAsync method that throws, and we want to create a TryParseIntAsync that doesn't throw. We could implement it like this:
public static Task<bool> TryParseIntAsync(string s, out Task<int> result)
{
var tcs = new TaskCompletionSource<int>();
result = tcs.Task;
return ParseIntAsync(s).ContinueWith(t =>
{
if (t.IsFaulted)
{
tcs.SetException(t.Exception.InnerException);
return false;
}
tcs.SetResult(t.Result);
return true;
}, default, TaskContinuationOptions.None, TaskScheduler.Default);
}
Using the TaskCompletionSource and the ContinueWith method is a bit awkward, but there is no other option since we can't use the convenient await keyword inside this method.
Usage example:
if (await TryParseIntAsync("-13", out var result))
{
Console.WriteLine($"Result: {await result}");
}
else
{
Console.WriteLine($"Parse failed");
}
Update: If the async logic is too complex to be expressed without await, then it could be encapsulated inside a nested asynchronous anonymous delegate. A TaskCompletionSource would still be needed for the out parameter. It is possible that the out parameter could be completed before
the completion of the main task, as in the example bellow:
public static Task<string> GetDataAsync(string url, out Task<int> rawDataLength)
{
var tcs = new TaskCompletionSource<int>();
rawDataLength = tcs.Task;
return ((Func<Task<string>>)(async () =>
{
var response = await GetResponseAsync(url);
var rawData = await GetRawDataAsync(response);
tcs.SetResult(rawData.Length);
return await FilterDataAsync(rawData);
}))();
}
This example assumes the existence of three asynchronous methods GetResponseAsync, GetRawDataAsync and FilterDataAsync that are called
in succession. The out parameter is completed on the completion of the second method. The GetDataAsync method could be used like this:
var data = await GetDataAsync("http://example.com", out var rawDataLength);
Console.WriteLine($"Data: {data}");
Console.WriteLine($"RawDataLength: {await rawDataLength}");
Awaiting the data before awaiting the rawDataLength is important in this simplified example, because in case of an exception the out parameter will never be completed.
I think using ValueTuples like this can work. You have to add the ValueTuple NuGet package first though:
public async void Method1()
{
(int op, int result) tuple = await GetDataTaskAsync();
int op = tuple.op;
int result = tuple.result;
}
public async Task<(int op, int result)> GetDataTaskAsync()
{
int x = 5;
int y = 10;
return (op: x, result: y):
}
Pattern matching to the rescue! C#9 (I think) onwards:
// example of a method that would traditionally would use an out parameter
public async Task<(bool success, int? value)> TryGetAsync()
{
int? value = // get it from somewhere
return (value.HasValue, value);
}
Use it like this:
if (await TryGetAsync() is (true, int value))
{
Console.WriteLine($"This is the value: {value}");
}
This is very similar to the answer provided by Michael Gehling, but I had my own solution until I found his and noticed that I wasn't the first to think of using an implicit conversion.
Regardless, I wanted to share as mine also supports when nullable is set to enable
public readonly struct TryResult<TOut>
{
#region constructors
public TryResult(bool success, TOut? value) => (Success, Value) = (success, value);
#endregion
#region properties
public bool Success { get; init; }
[MemberNotNullWhen(true, nameof(Success))] public TOut? Value { get; init; }
#endregion
#region methods
public static implicit operator bool(TryResult<TOut> result) => result.Success;
public static implicit operator TryResult<TOut>(TOut value) => new (true, value);
public void Deconstruct(out bool success, out TOut? value) => (success, value) = (Success, Value);
public TryResult<TOut> Out([NotNullWhen(true)] out TOut? value)
{
value = Value;
return this;
}
#endregion
}
Then you can write a Try method like this:
public static async Task<TryResult<byte[]>> TryGetBytesAsync(string file) =>
File.Exists(file)
? await File.ReadAllBytesAsync(file)
: default(TryResult<byte[]>);
And call it like this:
if ((await TryGetBytesAsync(file)).Out(out var bytes))
Console.WriteLine($"File has {bytes.Length} bytes.");
For developers who REALLY want to keep it in parameter, here might be another workaround.
Change the parameter to an array or List to wrap the actual value up. Remember to initialize the list before sending into the method. After returned, be sure to check value existence before consuming it. Code with caution.
You can do this by using TPL (task parallel library) instead of direct using await keyword.
private bool CheckInCategory(int? id, out Category category)
{
if (id == null || id == 0)
category = null;
else
category = Task.Run(async () => await _context.Categories.FindAsync(id ?? 0)).Result;
return category != null;
}
if(!CheckInCategory(int? id, out var category)) return error
Is it possible to somehow invoke inline try statement in C#?
I'm detecting languages for my website and sometimes, when language is something like en-GR on client side for some reason .NET throws exception. So I need to use try and also catch even though I'm not really catching anything.
It just seems as a total overkill in this situation.
// Set allowed languages
string[] allowedLanguages = { "en", "fr", "ru" };
// Get all possible values
var routeLanguage = (filterContext.RouteData.Values["lang"] != null && allowedLanguages.Contains(filterContext.RouteData.Values["lang"].ToString())) ? filterContext.RouteData.Values["lang"].ToString() : null;
var cookieLanguage = (filterContext.HttpContext.Request.Cookies["lang"] != null && allowedLanguages.Contains(filterContext.HttpContext.Request.Cookies["lang"].Value)) ? filterContext.HttpContext.Request.Cookies["lang"].Value : null;
string clientLanguage = null;
try
{
clientLanguage = (filterContext.HttpContext.Request.UserLanguages != null) ? new CultureInfo(filterContext.HttpContext.Request.UserLanguages[0]).TwoLetterISOLanguageName : null; // Exception sometimes without `try`
}
catch (Exception)
{
}
Edit
Exception is not something I can fix since I have no control over what user has in his culture info. .NET just sees en-FR as invalid one.
First off, it is always better to figure out how to avoid the exception in the first place. Concentrate on that first. There is some reason why that exception is being thrown, and if you can determine what it is, then don't do that.
To actually answer your question: there is no out-of-the-box "eat all the exceptions in this expression" mechanism, but building your own is straightforward:
static T EatExceptions(Func<T> func)
{
try { return func(); } catch { }
return default(T);
}
...
clientLanguage = (filterContext.HttpContext.Request.UserLanguages != null) ?
EatExceptions(() => new CultureInfo(filterContext.HttpContext.Request.UserLanguages[0]).TwoLetterISOLanguageName) :
null; }
If someone tried to pull shenanigans like that in code I was reviewing then I would... well let's just say that the change would not get checked in. Eating exceptions like this is a very bad idea 99% of the time. Again: figure out what you are doing wrong and stop doing it. Don't do something wrong and then handle the failure.
Have you tried getting rid of the try/catch statement completely?
string clientLanguage = null;
var userLanguages = filterContext.HttpContext.Request.UserLanguages;
if (userLanguages != null && userLanguages.Length > 0)
{
var culture = CultureInfo
.GetCultures(CultureTypes.AllCultures)
.FirstOrDefault(
x => string.Equals(
x.Name,
userLanguages[0].Name,
StringComparison.OrdinalIgnoreCase
)
);
if (culture != null)
{
clientLanguage = culture.TwoLetterISOLanguageName;
}
}
Use try/catch only for handling exceptions that are out of your control. As their name suggests exceptions should be used for handling exceptional cases.
In this case you are doing standard parsing so it is much better to do defensive programming instead of trying, throwing, catching, ...
_.Try(() => __YourStatementHere__ );
Using a little helper class like this:
/// <summary>
/// Other utility functions.
/// </summary>
public static class _ {
/// <summary>
/// Tries to execute the given action. If it fails, nothing happens.
/// </summary>
public static void Try(Action action) {
try {
action();
}
catch {
}
}
}
I know, this solution is not optimal either, but up to now the most concise one I could find.
First try to avoid the exception. Just because the string comes from a source you don't control, doesn't mean you can't validate it.
If you can't avoid it, you should catch the specific exception you expect and encapsulate that logic in a method. Don't catch all exceptions.
For example:
public static CultureInfo TryGetCultureByName(string name)
{
try
{
return new CultureInfo(name);
}
catch(CultureNotFoundException)//Only catching CultureNotFoundException
{
return null;
}
}
That way, if you later discover a better way to handle this specific error, you can easily replace it.
For example you could create a Dictionary<string, CultureInfo>, fill it from CultureInfo.GetCultures() and use TryGetValue to look up a culture without ever throwing an exception.
What you did is the right way to do it. You stated, why you cannot get rid of the exception (and I assume this is the case). So you have to handle it. Alas, C# does not have a try-catch as an expression (not sure how that would work - the catch "clause" would need to return a value).
Alternatively you can build a little helper function that takes a Func<T>, invokes it and passes through the value to the caller. If an exception occurres it returns (for example) default(T). That takes away a lot of the clutter and is reusable.
Well, leaving aside the (good) advice about pre-checking, there are several rather mundane/prosaic/obvious ways to do this:
First, you could wrap it in a function. I assume that this would not be general enough for you.
Or, you could collapse the catch branch:
try
{
clientLanguage = (filterContext.HttpContext.Request.UserLanguages != null) ? new CultureInfo(filterContext.HttpContext.Request.UserLanguages[0]).TwoLetterISOLanguageName : null; // Exception sometimes without `try`
} catch (Exception) { }
Or, you could just collapse the whole thing to a single line:
try { clientLanguage = (filterContext.HttpContext.Request.UserLanguages != null) ? new CultureInfo(filterContext.HttpContext.Request.UserLanguages[0]).TwoLetterISOLanguageName : null; } catch (Exception) { }
Not elegant, but simple, and it works.
This is one another way:
await new #try(async () => { user = await GetItemAsync(userId); })
.#catch<Exception>(async () => { user = new User(); });
I think it's more verbose than the try/catch:
try { return await GetItemAsync(userId); }
catch (Exception ex) { return new User(); }
The helper class:
public class #try
{
private Func<Task> func;
private Action action;
public #try(Func<Task> func)
{
this.func = func;
}
public #try(Action action)
{
this.action = action;
}
public async Task #catch<T>(Func<Task> fallback) where T : Exception
{
try
{
await func.Invoke();
}
catch(T ex)
{
await fallback.Invoke();
}
}
public void #catch<T>(Action fallback) where T : Exception
{
try
{
action.Invoke();
}
catch (T ex)
{
fallback.Invoke();
}
}
}
I've built an in-line try catch mechanic that may suit this purpose. I was going for a sort of LINQ-like or Callback function-y syntax. This is done using a couple of wrappers, a TryWrapper and a CatchWrapper so that the dot operators prompt the next steps appropriately, that implicitly cast to type of T.
You could also do something like
Try(() => UpdateSweetGreen("21", SweetGreen))
.Catch(LogToDb(e.Message))
.Catch(LogToFile(e.Message).Finally(ReportNewSweetGreen(SweetGreen);
Basically a CatchWrapper extends TryWrapper. So you could catch an exception off of another catch block. In this instance logging a failure of your method to a database, then if that fails to a file, then no matter what reporting the SweetGreen variable to some other component.
This all extends from TryWrapper
public class TryWrapper<T>
{
protected internal T Result { get; set; } = default(T);
protected internal Exception Exception { get; set; } = null;
public static implicit operator T(TryWrapper<T> wrapper)
{
return wrapper.Result;
}
public static implicit operator Exception(TryWrapper<T> wrapper)
{
return wrapper.Exception;
}
}
and CatchWrapper which simply extends TryWrapper and cannot be invoked directly, instead only appearing after a try as you'd expect with standard implementation
public class CatchWrapper<T> : TryWrapper<T>
{
}
Then a series of static extension methods
public static TryWrapper<T> Try<T>(Func<T> func)
{
var product = new TryWrapper<T>();
try
{
product.Result = func.Invoke();
}
catch (Exception e)
{
product.Exception = e;
}
return product;
}
public static TryWrapper<T> Try<T>(Action action)
{
var product = new TryWrapper<T>();
try
{
action.Invoke();
}
catch (Exception e)
{
product.Exception = e;
}
return product;
}
public static CatchWrapper<T> Catch<T>(this TryWrapper<T> wrapper, Action<Exception> response)
{
if (wrapper.Exception is null) return wrapper as CatchWrapper<T>;
response.Invoke(wrapper);
wrapper.Exception = null;
return wrapper as CatchWrapper<T>;
}
public static TryWrapper<T> Finally<T>(this TryWrapper<T> wrapper, Action<T> response)
{
response.Invoke(wrapper);
return wrapper;
}
public static TryWrapper<T> Finally<T>(this TryWrapper<T> wrapper, Func<T> response)
{
wrapper.Result = response.Invoke();
return wrapper;
}
public static TryWrapper<T> Finally<T>(this TryWrapper<T> wrapper, Action response)
{
response.Invoke();
return wrapper;
}
Now this does achieve that inline syntax the OP was asking for but I'd hazard to say its a touch less efficient since you could just deal with the exception directly in a standard try-catch. Still kindof cool to be able to specify the return directly before the Try, though this is risky if defaults to null.
Im still kinda new to c# and there's something I cant quite get to grips with:
In VBA for example, if there is a bit of code I need throughout an app I would put it in a function then call it where ever I need it just by using the name of the function, eg
Sub Something()
If variable = x then
RunMyFunction
end if
End Sub
Is there a similar way of calling re-usable code in c#? I do realise its a completely different beast to what Ive worked with before
thanks
private void Something()
{
if (variable == x)
{
RunMyFunction();
}
}
private void RunMyFunction()
{
// does something
}
In other words - it is basically the same. You define your resuable function as a method (RunMyFunction above) and then call it by name (with parenthesis).
Yes C# comes with functions as well. Sub is actually a function with void "return value".
So crude translation of your code to C# will be:
string RunMyFunction()
{
return "hello";
}
void Something(variable, x)
{
if (variable == x)
{
string value = RunMyFunction();
//.....
}
}
Yes, I sometimes create a new class called CommonFunctions.cs, and inside this class I would have the methods:
public class CommonFunctions
{
public static void Something(int Variable)
{
if(Variable == 5)
CommonFunctions.RunAnother();
}
public static void RunAnother()
{
}
}
Here is an example of a function:
public int AddNumbers(int number1, int number2)
{
int result = number1 + number2;
if(result > 10)
{
return result;
}
}
You might find this article useful:
http://csharp.net-tutorials.com/basics/functions/
The biggest departure you'll need to make from VBA is that C# is truly object-oriented. You'll have to get used to the idea of functions being a member of a class that you have to instantiate (in most cases).
If your function do not return value use void:
private void FunctionName ()
{
// Do something...
}
If function return value than function have value type before function name:
private int FunctionNameReturnInt(int a, int b)
{
// Do something...
int res = a + b;
return num;
}
...
// Calling functions
FunctionName();
int res;
res = FunctionNameReturnInt(1,2);
`