c# - 为什么我不能在我的 Web API 项目中使用带有 C# 异步函数的 Discard 作为触发后遗忘机制
问题描述
我正在编写一个 Web API 项目,并且对于我的一个端点(HandleAsync
方法是实现)我无法使用丢弃语法(_
),我不知道为什么。
我还有其他地方采用相同的模式:调用CheckoutFileAsync
并且在委托中调用processNotifications
时可以正常使用。_
SendEmailAsync
唯一的区别是IfContentManagementAuthorizedAsync
代替 的不同条目IfFileActionAuthorizedAsync
,但是如果授权逻辑中的一切都很好,则每个条目都具有异步回调的“相同”概念。
我收到的编译错误在这一行
_ = emailService.SendEmailAsync(
这是错误:
无法将类型“System.Threading.Tasks.Task”隐式转换为“bool”
如果我将鼠标悬停在 上_
,intellisense 会说(parameter) bool _
。如果我将鼠标悬停_
在它工作的地方,它会说(discard) Task<bool> _
。
我基本上想要一个“即发即弃”的机制来发送通知电子邮件。我不想处理结果或等待可能发生的任何延迟,据我了解,丢弃语法是我应该做的模式。鉴于下面的代码,您是否看到我不能使用丢弃语法的任何原因?
请注意,我有两个If*AuthorizedAsync
方法重载,一个返回Task<IActionResult>
,另一个返回,Task<ActionResult<T>>
因为它们用于我的所有端点,它们的返回类型不同,我无法弄清楚如何使一个签名适用于所有端点。
public async Task<IActionResult> HandleAsync( [FromQuery] FileIdParameters parameters )
{
var fileInfo = await GetFilePropertiesAsync<DataLockerFile>( parameters.Id, null );
if ( fileInfo == null )
{
return NotFound();
}
return await IfFileActionAuthorizedAsync(
"Write",
fileInfo.FolderName,
async ( user, userEmail, canCreateFolder ) =>
await CheckoutFileAsync(
userEmail,
fileInfo,
dateTimeService.UtcNow,
fileInfo =>
{
_ = emailService.SendEmailAsync(
string.Join( ";", notificationEmails ),
emailService.DefaultFrom,
$"KAT Management Secure File Checkout: {fileInfo.FolderName}:{fileInfo.Name}",
$"{user} has checked out {fileInfo.FolderName}:{fileInfo.Name}."
);
}
)
);
}
protected async Task<ActionResult<T>> IfFileActionAuthorizedAsync<T>(
string requiredClaim, string folder,
Func<string, string, bool, Task<ActionResult<T>>> validResult )
{
var claimResult = Foo(); // .. logic
return await validResult( claimResult.User, claimResult.UserEmail, claimResult.CanCreateFolder );
}
protected async Task<IActionResult> IfFileActionAuthorizedAsync(
string requiredClaim, string folder,
Func<string, string, bool, Task<IActionResult>> validResult )
{
var claimResult = Foo(); // .. logic
return await validResult( claimResult.User, claimResult.UserEmail, claimResult.CanCreateFolder );
}
protected async Task<IActionResult> CheckoutFileAsync(
string userEmail,
DataLockerBaseFile fileInfo,
DateTime checkoutTime,
Action<DataLockerBaseFile> processNotifications
)
{
var fileInfo = await DoSomethingAsync(); // logic
processNotifications( fileInfo );
return Ok();
}
// This method is part of another class, the smtp configuration object is inject with DI
public async Task<bool> SendEmailAsync( string to, string from, string subject, string body )
{
var message = CreateMailMessage( to, from, subject body );
var mailClient = new SmtpClient( smtp.Server );
mailClient.Credentials = new System.Net.NetworkCredential( smtp.UserName, smtp.Password );
await mailClient.SendMailAsync( message );
return true;
}
解决方案
IntelliSense 悬停表示问题:
如果我将鼠标悬停在 _ 上,智能感知会说
(parameter) bool _
。
导致此问题的代码使用一种通用模式来处理排序但不是真正丢弃的参数值,其中之一是bool
. 例如,它可能有一些 lambda 形式(arg, _ /* unneeded boolean argument */) => { ... }
。附带说明一下,您发布的代码没有这种模式,也不会导致问题;在简化要发布的代码时,请确保您最终发布的代码确实重现了问题。
这是表示“不需要此参数”的常见模式;但是,这并不是语言级别的实际丢弃(C# 9.0 中的某些情况除外)。相反,它实际上定义了一个名为_
type的参数bool
。
因此,丢弃模式_ = ...
不适用于该代码块。由于有一个名为 的实际参数_
,编译器将其视为对该参数的赋值,并给出错误:
无法将类型“System.Threading.Tasks.Task”隐式转换为“bool”
_
解决方案是将 sort-of-discard 参数从 重命名为__
. 然后丢弃模式将起作用。
另一方面,“即发即弃”几乎总是错误的解决方案。
推荐阅读
- docker - Dockerfile 用于创建一个图像以在 jenkins 中用作容器代理
- linux - Docker 19.03 中是否有用于访问 docker buildx 的 HTTP api?
- ios - 为什么我的 IBAction 出现“无法识别的选择器”错误?
- c# - 尝试读取 excel 但如果用户删除行会得到 System.ArgumentOutOfRangeException
- sql - 获取sql server中proc所有输出的行数
- selenium - 从不同的包调用java类
- jquery - 发送 csv 文件熔断节点
- java - 使用JPQL JpaRepository从两个表父表ID一对多关系中检索数据
- java - 我的代码有问题,我想在详细活动中显示我的产品价格,但是当我构建我的应用程序时我被强制关闭
- protractor - 量角器黄瓜配置文件无法识别黄瓜 stepdefinition 文件