CS1988|C#无法在异步方法中使用ref,in,out类型的参数
🌀|场景:
BlazorServer的场景中推荐使用异步方法,使用ref,out,in为参数前缀则报错CS1988
原因如下:
ref
parameters are not supported inasync
methods because the method may not have completed when control returns to the calling code. Any changes to the referenced variables will not be visible to the calling code, resulting in a CS1988 error.
async
方法不支持ref
参数,因为当控件返回到调用代码时,该方法可能尚未完成。 对引用变量的任何更改都对调用代码不可见,从而导致 CS1988 错误。
⛵️|替代方法:
将需要用到的参数作为Task的返回,即
💥|延申:引用变量的可见性
1.当不使用基础类型为参数,使用引用类型时:
现有Blazor页面如下
@page "/login"
@using KatexTest2.Models
@using KatexTest2.Utils
@inject MyAuthProvider provider
<h3>LoginPage</h3>
<AuthorizeView>
<NotAuthorized>
@if(Isfailed){
<span>用户名或密码错误</span>
}
@if (test.Number==114.514M)
{
<span>压力吗室内</span>
}
<EditForm id = "LP" Model="loginModel" Context="Login">
<div>
<label> Username:
<InputText @bind-Value="loginModel.Username"></InputText>
</label>
</div>
<div>
<label> Password:
<InputText type="password" @bind-Value="loginModel.Password"></InputText>
</label>
</div>
<div>
<button @onclick="TryLogin">Submit</button>
</div>
</EditForm>
</NotAuthorized>
<Authorized>
<button type="button" class="btn btn-primary" @onclick="TryLogout" ></button>
</Authorized>
<Authorizing>
<span>翼沿丁真</span>
</Authorizing>
</AuthorizeView>
@code {
public class RefTest
{
public string Context { get; set; } = "DefaultContext";
public decimal Number { get; set; } = 11.54M;
}
[Parameter]
public Boolean Isfailed { get; set; } = false;
public RefTest test { get; set; } = new();
private LoginFormModel loginModel { get; set; } = new();
private async Task TryLogin()
{
Isfailed = await provider.LoginAsync(loginModel,test);
}
private async Task TryLogout()
{
await provider.LogoutAsync();
}
}
修改LoginAsync方法如下:
public async Task<Boolean> LoginAsync(LoginFormModel loginFormModel,RefTest test)
{
var (userInDatabase, isSuccess) = LookUpUser(loginFormModel.Username, loginFormModel.Password);
var principal = new ClaimsPrincipal();
if (isSuccess)
{
var identity = CreateIdentityFromUser(userInDatabase);
principal = new ClaimsPrincipal(identity);
await _protectedLocalStorage.SetAsync("identity", JsonConvert.SerializeObject(userInDatabase));
}
else
{
test.Number = 114.514M;
}
NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(principal)));
await jsRuntime.InvokeVoidAsync("alert", new object[1] { "WTF" });
return !isSuccess;
}
运行测试:
从图中可以看出:
在方法的运行时间内,razor page并不能获取对象信息改变的值(运行完成后可以),如果是一些运行时间长的方法,则可能造成一些响应不及时的效果。例如拿掉权限后依旧可以访问一些东西
🔚|结论:
如果要在async方法中获取一些返回值,请直接加在的Task的返回中。
应避免使用引用类型为参数来充当返回值。