Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/292.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 返回列表元素时的协方差错误<;DerivedClass>;_C#_C# 4.0_Covariance - Fatal编程技术网

C# 返回列表元素时的协方差错误<;DerivedClass>;

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

我正在处理一个让我头疼的问题。我一直在读一些关于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: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是一个IFileDataExcelFileReader是一个读卡器,它通过流返回一个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[])
图像也可能有帮助:

正如我所说,我相信误差与协方差有关,但我不能完全确定。我猜编译器似乎没有得到JETFileDataIFileData的信息。
我做错了什么?

我不认为这与协方差有任何关系,相反,问题是您试图更改覆盖方法中的返回类型

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));
    }
}