返回 List<DerivedClass> 的元素时出现协方差错误
covariance error when returning an element of List<DerivedClass>
我正在处理一个让我头疼的问题。我一直在阅读一些关于 C# 中与协变和逆变相关的问题的帖子,但似乎任何东西都可以解决这个问题。
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 抽象 class 它公开了一个方法 GetReader() returns 一个IBaseReader到某个IFileData。如果您查看 IBaseReader 的声明,它会指定与协方差概念相关的“out”关键字。
在其他程序集中,我已经声明了一些使用这些的 classes。
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和ExcelFileReader 是一个 reader,它传递一个 Stream returns a JETFileData
然后我有一个从 BaseImporter 派生的具体导入器。例如:
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));
}
}
因此,错误显示:
'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[])'
图片也可能有帮助:
正如我所说,我认为错误与协方差有关,但我不完全确定。我猜编译器似乎没有得到 JETFileData 是一个 IFileData。
我做错了什么?
我认为这与协方差没有任何关系,问题在于您正试图在覆盖方法中更改 return 类型。
将 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);
}
然后,当您在 US_ETDocumentImporter
中覆盖它时,您会得到您想要的:
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));
}
}
我正在处理一个让我头疼的问题。我一直在阅读一些关于 C# 中与协变和逆变相关的问题的帖子,但似乎任何东西都可以解决这个问题。
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 抽象 class 它公开了一个方法 GetReader() returns 一个IBaseReader到某个IFileData。如果您查看 IBaseReader 的声明,它会指定与协方差概念相关的“out”关键字。
在其他程序集中,我已经声明了一些使用这些的 classes。
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和ExcelFileReader 是一个 reader,它传递一个 Stream returns a JETFileData
然后我有一个从 BaseImporter 派生的具体导入器。例如:
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));
}
}
因此,错误显示:
'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[])'
图片也可能有帮助:
正如我所说,我认为错误与协方差有关,但我不完全确定。我猜编译器似乎没有得到 JETFileData 是一个 IFileData。 我做错了什么?
我认为这与协方差没有任何关系,问题在于您正试图在覆盖方法中更改 return 类型。
将 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);
}
然后,当您在 US_ETDocumentImporter
中覆盖它时,您会得到您想要的:
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));
}
}