如何将 `Task<string>` 实例用作方法的 Task<string?> 参数?
How can I use a `Task<string>` instance as a Task<string?> parameter to a method?
如何使用 Task<string>
实例作为方法的 Task 参数?
如果我启用了可空性,并且我有两个异步方法,例如..
// in an ordinary class
public async static Task<string> Foo() { ... }
// in a static class
public async static Task Bar(this Task<string?> task1) { ... }
我尝试调用 await Foo().Bar();
,但编译器给我:
warning CS8620: Argument of type 'Task<string>' cannot be used for parameter 'task' of type 'Task<string?>'
我可以对 Foo 的结果做些什么才能使其作为 Task 接受?
您可以将 Task<string>
包装在 return 作为 Task<string?>
结果的延续中:
await Foo().ContinueWith<string?>(task => {
try {
return task.Result;
} catch (AggregateException e) {
throw e.InnerExceptions[0]; // Propagate exceptions/cancellation.
}
}).Bar();
ContinueWith
中的 lambda 表达式必须 return 一个 string?
,它在这里起作用,因为 task.Result
是一个 string
,它可以隐式转换为 string?
.
有人提议Task nullability covariance。
目前,您必须使用 ! (null-forgiving) operator 来消除编译器警告:
await FooClass.Foo()!.Bar();
class Program
{
static async Task Main(string[] args)
{
await FooClass.Foo()!.Bar();
}
}
public static class Extensions
{
public async static Task Bar(this Task<string?> task)
{
System.Console.WriteLine("bar");
await Task.CompletedTask;
}
}
public class FooClass
{
public async static Task<string> Foo()
{
System.Console.WriteLine("foo");
return await Task.FromResult("");
}
}
问题是 C# 的可空引用类型注释不是泛型类型的变体。
这段代码证明了这一点:
Task<object> o = Task.FromResult<object>(new object());
Task<object?> p = o;
虽然我们知道一个不能 return null 的任务应该被允许代替一个可以 return null 的任务,但编译器并不知道这一点。
编译这个gives warning:
CS8619: Nullability of reference types in value of type 'Task' doesn't match target type 'Task<object?>'.
请注意,此差异适用于委托和接口。但是 Task<T>
两者都不是。
例如,这两个 compile without warning:
IEnumerable<object> c = new[] { new object() };
IEnumerable<object?> d = c;
Action<object?> a = _ => {};
Action<object> b = a;
已经讨论过在 Task<T>
中针对 T
的可空性向编译器添加特殊处理,但尚未落地。
到那个时候,您必须使用 null 宽恕运算符来抑制这些警告。
如何使用 Task<string>
实例作为方法的 Task
如果我启用了可空性,并且我有两个异步方法,例如..
// in an ordinary class
public async static Task<string> Foo() { ... }
// in a static class
public async static Task Bar(this Task<string?> task1) { ... }
我尝试调用 await Foo().Bar();
,但编译器给我:
warning CS8620: Argument of type 'Task<string>' cannot be used for parameter 'task' of type 'Task<string?>'
我可以对 Foo 的结果做些什么才能使其作为 Task
您可以将 Task<string>
包装在 return 作为 Task<string?>
结果的延续中:
await Foo().ContinueWith<string?>(task => {
try {
return task.Result;
} catch (AggregateException e) {
throw e.InnerExceptions[0]; // Propagate exceptions/cancellation.
}
}).Bar();
ContinueWith
中的 lambda 表达式必须 return 一个 string?
,它在这里起作用,因为 task.Result
是一个 string
,它可以隐式转换为 string?
.
有人提议Task nullability covariance。
目前,您必须使用 ! (null-forgiving) operator 来消除编译器警告:
await FooClass.Foo()!.Bar();
class Program
{
static async Task Main(string[] args)
{
await FooClass.Foo()!.Bar();
}
}
public static class Extensions
{
public async static Task Bar(this Task<string?> task)
{
System.Console.WriteLine("bar");
await Task.CompletedTask;
}
}
public class FooClass
{
public async static Task<string> Foo()
{
System.Console.WriteLine("foo");
return await Task.FromResult("");
}
}
问题是 C# 的可空引用类型注释不是泛型类型的变体。
这段代码证明了这一点:
Task<object> o = Task.FromResult<object>(new object());
Task<object?> p = o;
虽然我们知道一个不能 return null 的任务应该被允许代替一个可以 return null 的任务,但编译器并不知道这一点。
编译这个gives warning:
CS8619: Nullability of reference types in value of type 'Task' doesn't match target type 'Task<object?>'.
请注意,此差异适用于委托和接口。但是 Task<T>
两者都不是。
例如,这两个 compile without warning:
IEnumerable<object> c = new[] { new object() };
IEnumerable<object?> d = c;
Action<object?> a = _ => {};
Action<object> b = a;
已经讨论过在 Task<T>
中针对 T
的可空性向编译器添加特殊处理,但尚未落地。
到那个时候,您必须使用 null 宽恕运算符来抑制这些警告。