[英]How do I overload function to accept both async and synchronized version of callback parameter
public static T SyncVer<T>(Func<T> callback)
{
using (new LogContext("new logging context"))
{
try
{
return callback();
}
catch (Exception ex)
{
Console.WriteLine(ex);
throw;
}
}
}
public static async Task<T> AsyncVer<T>(Func<Task<T>> callback)
{
using (new LogContext("new logging context"))
{
try
{
return await callback();
}
catch (Exception ex)
{
Console.WriteLine(ex);
throw;
}
}
}
Please consider the code above.请考虑上面的代码。 You may see most of the code in both functions are the same.
您可能会看到两个函数中的大部分代码是相同的。 I am finding a way to group them up by overloading them into one (or if there a way to take out the similar part of both function) so that I don't need to duplicate the content?
我正在寻找一种通过将它们重载为一个来将它们分组的方法(或者如果有办法取出两个函数的相似部分),这样我就不需要复制内容了?
Any help provided will be appreciated.提供的任何帮助将不胜感激。 Thanks in advance.
提前致谢。
I would try something like this:我会尝试这样的事情:
public static T SyncVer<T>(Func<T> callback)
{
return AsyncVer(() => Task.FromResult(callback())).GetAwaiter().GetResult();
}
Note that Task.FromResult
will allocate, and GetAwaiter().GetResult()
may dead lock注意
Task.FromResult
会分配, GetAwaiter().GetResult()
可能会死锁
Personally I would just create two methods and not worry about it.就我个人而言,我只会创建两种方法而不用担心它。
However, another (and slightly safer) approach is to wrap your callbacks in a ValueTask
.但是,另一种(并且稍微安全一点)的方法是将回调包装在
ValueTask
中。 ValueTasks
work best if they execute synchronously, however they have a few subtle limitations and should never be awaited more than once.如果
ValueTasks
同步执行,它们的工作效果最好,但是它们有一些微妙的限制,并且永远不应等待超过一次。
The assumption is, this is all about creation an awaitable and non awaitable delegate overload, code reuse, and awaiting the sync version of this call is not a problem for you.假设是,这一切都是关于创建一个可等待和不可等待的委托重载、代码重用,并且等待此调用的同步版本对您来说不是问题。
Given给定
public static async ValueTask<T> SomethingAsync<T>(Func<T> callback)
=> await SomethingAsync(() => new ValueTask<T>(callback()));
public static async ValueTask<T> SomethingAsync<T>(Func<Task<T>> callback)
=> await SomethingAsync(() => new ValueTask<T>(callback()));
public static async ValueTask<T> SomethingAsync<T>(Func<ValueTask<T>> callback)
{
using (new LogContext("new logging context"))
{
try
{
return await callback();
}
catch (Exception ex)
{
Console.WriteLine(ex);
throw;
}
}
}
Usage用法
public static string DoSomething()
{
Console.WriteLine("execute sync");
return "sync result";
}
public static async Task<string> DoSomethingAsync()
{
Console.WriteLine("Execute async");
await Task.Delay(100);
return "async result";
}
...
Console.WriteLine(await SomethingAsync(DoSomething));
Console.WriteLine(await SomethingAsync(DoSomethingAsync));
Output Output
Create
execute sync
Dispose
sync result
Create
Execute async
Dispose
async result
To add some more efficiencies you can elide wrappers要增加一些效率,您可以省略包装器
Exmaple示例
public static ValueTask<T> SomethingAsync<T>(Func<T> callback)
{
try
{
return SomethingAsync(() => new ValueTask<T>(callback()));
}
catch (Exception e)
{
return ValueTask.FromException<T>(e);
}
}
public static ValueTask<T> SomethingAsync<T>(Func<Task<T>> callback)
{
try
{
return SomethingAsync(() => new ValueTask<T>(callback()));
}
catch (Exception e)
{
return ValueTask.FromException<T>(e);
}
}
Note : ValueTask.FromException
is only available for .NET 5.0+注意:
ValueTask.FromException
仅适用于 .NET 5.0+
The benefits of this approach:这种方法的好处:
The downsides are缺点是
Note: I personally have never had a need to do this, I would just create the two methods ¯\_(ツ)_/¯
.注意:我个人从来不需要这样做,我只会创建两个方法
¯\_(ツ)_/¯
。
Additional resources其他资源
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.