C# 返回列表元素时的协方差错误<;DerivedClass>;
我正在处理一个让我头疼的问题。我一直在读一些关于C#中协方差和逆变换相关问题的帖子,但似乎任何东西都能解决这个问题C# 返回列表元素时的协方差错误<;DerivedClass>;,c#,c#-4.0,covariance,C#,C# 4.0,Covariance,我正在处理一个让我头疼的问题。我一直在读一些关于C#中协方差和逆变换相关问题的帖子,但似乎任何东西都能解决这个问题 public abstract class BaseImporter<TEntity> : IImporter<TEntity> where TEntity : class { //don't pay attention to this method public TEntity SomeMethodWhichUsesTheGenericTy
public abstract class BaseImporter<TEntity> : IImporter<TEntity> where TEntity : class
{
//don't pay attention to this method
public TEntity SomeMethodWhichUsesTheGenericType();
//this is the important one
protected abstract IBaseReader<IFileData> GetReader(Stream file, params object[] args);
}
public interface IImporter<out T> where T : class
{
//don't pay attention to this method
T SomeMethodWhichUsesTheGenericType();
}
public interface IBaseReader<out T> where T : IFileData
{
T GetFileData(Stream stream);
bool CanHandleStream(Stream stream, params object[] args);
}
public interface IFileData
{
}
公共抽象类BaseImporter:IImporter,其中tenty:class
{
//不要注意这个方法
使用GenericType()的公共方法;
//这是最重要的
受保护的抽象iBaserReader GetReader(流文件,参数对象[]args);
}
公共接口输入程序,其中T:class
{
//不要注意这个方法
T使用GenericType()的某些方法;
}
公共接口IBaseReader,其中T:IFileData
{
T GetFileData(流);
bool CanHandleStream(流,参数对象[]args);
}
公共接口IFileData
{
}
看,我已经创建了一个BaseImporter抽象类,它公开了一个方法GetReader(),该方法将IBaseReader返回给某个IFileData。如果查看iBaserReader的声明,它会指定与协方差概念相关的“out”关键字
在另一个程序集中,我声明了一些使用这些类的类
public class JETFileData : IFileData
{
List<string> Data { get; set; }
}
public class ExcelFileReader : BaseReader<JETFileData>
{
public override bool CanHandleStream(Stream stream, params object[] args)
{
return true;
}
public override JETFileData GetFileData(Stream stream)
{
return new JetFileData() { Data = new List<string>() };
}
}
公共类JETFileData:IFileData
{
列表数据{get;set;}
}
公共类ExcelFileReader:BaseReader
{
公共覆盖布尔CanHandleStream(流,参数对象[]args)
{
返回true;
}
公共覆盖JETFileData GetFileData(流)
{
返回新的JetFileData(){Data=newlist()};
}
}
请注意,JETFileData是一个IFileData,ExcelFileReader是一个读卡器,它通过流返回一个JETFileData
然后我有一个具体的导入器,它来自BaseImporter。e、 g:
public class US_ETDocumentImporter : BaseImporter<US_ETDocument>
{
public List<IBaseReader<JETFileData>> Readers { get; set; }
public US_ETDocumentImporter()
{
this.Readers = new List<IBaseReader<JETFileData>>()
{
new ExcelFileReader()
};
}
//HERE IS WHERE I GOT THE ERROR!!!
protected override IBaseReader<JETFileData> GetReader(Stream file, params object[] args)
{
//decide which reader is able to be used to process this file
return this.Readers.Single(r => r.CanHandleStream(file, args));
}
}
公共类美国ETDocumentImporter:BaseImporter
{
公共列表读取器{get;set;}
美国公共文件进口商()
{
this.Readers=新列表()
{
新的ExcelFileReader()
};
}
//这里是我得到错误的地方!!!
受保护的覆盖iBaserReader GetReader(流文件,参数对象[]args)
{
//确定可以使用哪个读取器处理此文件
返回this.Readers.Single(r=>r.CanHandleStream(文件,args));
}
}
因此,错误是:
'Importers.US_ETDocumentImporter.GetReader(System.IO.Stream, params object[])': return type must be 'Core.IBaseReader<Core.IFileData>' to match overridden member 'Core.BaseImporter<Documents.US_ETDocument>.GetReader(System.IO.Stream, params object[])'
'Importers.US\ETDocumentImporter.GetReader(System.IO.Stream,params object[]):返回类型必须为'Core.ibaserReader'才能匹配重写的成员'Core.BaseImporter.GetReader(System.IO.Stream,params object[])
图像也可能有帮助:
正如我所说,我相信误差与协方差有关,但我不能完全确定。我猜编译器似乎没有得到JETFileData是IFileData的信息。
我做错了什么?我不认为这与协方差有任何关系,相反,问题是您试图更改覆盖方法中的返回类型 将
BaseImporter
更改为具有另一个泛型类型,并将其约束为IFileData
public abstract class BaseImporter<TEntity, TFileData> : IImporter<TEntity>
where TEntity : class
where TFileData: IFileData
{
//don't pay attention to this method
public TEntity SomeMethodWhichUsesTEntity()
{
return null;
}
// changed IFileData to TFileData
protected abstract IBaseReader<TFileData> GetReader(Stream file, params object[] args);
}
您没有向我们展示
BaseJETImporter
,这没有帮助。另外,我怀疑这里的很多细节是不必要的。。。你能试着把它简化成一个简短但完整的例子,里面没有任何无关的东西吗?我怀疑您可能需要另一个泛型类型参数,但目前很难确定。对不起,我试图简化问题,但该类不需要。我现在就纠正它。请记住,代码要长得多。。。所以我尽量让它更具可读性。每个方面都值得问问自己是否需要它。(我们需要了解读者吗?如果需要,我们真的需要知道他们正在从流中阅读吗?)将问题简化为最短的形式是关注问题核心的一个非常好的方法。@MauroBilotti:重写虚拟方法时,您不能更改签名。这与协方差完全无关。@MauroBilotti:您必须保留方法在基类中声明的签名。返回值的实际数据类型当然可以是子类型。太棒了!!!:它工作得很好。谢谢!我应该更改标题吗?因为对我来说一直是一个协方差问题,而事实并非如此。所以,问题在于,如果需要更改派生类上方法的签名,则需要在基类上指定泛型类型,以便进行向下更改。正如Dennis well所说,“您必须保留方法在基类中声明的签名”
public class US_ETDocumentImporter : BaseImporter<US_ETDocument,JETFileData>
{
public List<IBaseReader<JETFileData>> Readers { get; set; }
public US_ETDocumentImporter()
{
this.Readers = new List<IBaseReader<JETFileData>>()
{
new ExcelFileReader()
};
}
//HERE IS WHERE I GOT THE ERROR!!!
protected override IBaseReader<JETFileData> GetReader(Stream file, params object[] args)
{
//decide which reader is able to be used to process this file
return this.Readers.Single(r => r.CanHandleStream(file, args));
}
}