class ResultBase {}
class Result : ResultBase {}
Task<ResultBase> GetResult() {
return Task.FromResult(new Result());
}
Run Code Online (Sandbox Code Playgroud)
编译器告诉我它不能隐式转换Task<Result>为Task<ResultBase>.有人可以解释为什么会这样吗?我希望协方差可以让我以这种方式编写代码.
由于C#的Task是一个类,你显然无法将其转换Task<TDerived>为a Task<TBase>.
但是,你可以这样做:
public async Task<TBase> Run() {
return await MethodThatReturnsDerivedTask();
}
Run Code Online (Sandbox Code Playgroud)
是否有一个静态任务方法我可以调用来获取一个Task<TDerived>基本上只指向底层任务并转换结果的实例?我喜欢这样的东西:
public Task<TBase> Run() {
return Task.FromDerived(MethodThatReturnsDerivedTask());
}
Run Code Online (Sandbox Code Playgroud)
这种方法存在吗?是否仅为此目的使用异步方法有任何开销?
我有两个类:一个基类(Animal)和一个从它派生的类(Cat).Base类包含一个虚拟方法Play,它将List作为输入参数.这样的东西
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication9
{
class Animal
{
public virtual void Play(List<Animal> animal) { }
}
class Cat : Animal
{
public override void Play(List<Animal> animal)
{
}
}
class Program
{
static void Main(string[] args)
{
Cat cat = new Cat();
cat.Play(new List<Cat>());
}
}
}
Run Code Online (Sandbox Code Playgroud)
当我编译上面的程序时,我得到以下错误
Error 2 Argument 1: cannot convert from 'System.Collections.Generic.List' to 'System.Collections.Generic.List'
反正有没有完成这个?
C#4.0进一步扩展了通用类型和接口的协方差和逆变.有些接口(比如IEnumerable<T>)是协变量,所以我可以这样做:
IEnumerable<object> ie = new List<string>();
Run Code Online (Sandbox Code Playgroud)
但是这条线怎么样?我遇到了编译时错误
List<Object> list = new List<String>();
//Cannot implicitly convert type List<string>' to List<object>'
Run Code Online (Sandbox Code Playgroud)
我的意思是,如果List<T>实现IEnumerable<T>为什么List<T>仍然是不变的?有没有一个很好的反例可以解释为什么在C#中不允许这样做?