[英]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;
}
}
}
請考慮上面的代碼。 您可能會看到兩個函數中的大部分代碼是相同的。 我正在尋找一種通過將它們重載為一個來將它們分組的方法(或者如果有辦法取出兩個函數的相似部分),這樣我就不需要復制內容了?
提供的任何幫助將不勝感激。 提前致謝。
我會嘗試這樣的事情:
public static T SyncVer<T>(Func<T> callback)
{
return AsyncVer(() => Task.FromResult(callback())).GetAwaiter().GetResult();
}
注意Task.FromResult
會分配, GetAwaiter().GetResult()
可能會死鎖
就我個人而言,我只會創建兩種方法而不用擔心它。
但是,另一種(並且稍微安全一點)的方法是將回調包裝在ValueTask
中。 如果ValueTasks
同步執行,它們的工作效果最好,但是它們有一些微妙的限制,並且永遠不應等待超過一次。
假設是,這一切都是關於創建一個可等待和不可等待的委托重載、代碼重用,並且等待此調用的同步版本對您來說不是問題。
給定
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;
}
}
}
用法
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
Create
execute sync
Dispose
sync result
Create
Execute async
Dispose
async result
要增加一些效率,您可以省略包裝器
示例
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);
}
}
注意: ValueTask.FromException
僅適用於 .NET 5.0+
這種方法的好處:
缺點是
注意:我個人從來不需要這樣做,我只會創建兩個方法¯\_(ツ)_/¯
。
其他資源
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.