2

我有一个 classFileRecord和 class public class ZippedFileRecord : FileRecord,其中存储了SortedList mFiles所有 FileRecords 和 ZippedFileRecords。我遇到的问题是我需要一种方法来区分两者,每个 ZippedFileRecord 都有一个 FileRecord 和一个名为 GetFileRecord() 的方法,它解压缩与 ZippedFileRecord 关联的文件并为其创建一个 FileRecord(如在下面的块..)

    public class ZippedFileRecord : FileRecord
    {
        FileInfo zipFileInfo; //FileName, FileCreationTime/Date
        public FileRecord myRecord = null;
        public FileRecord GetFileRecord()
        {
            if (myRecord == null)
            {
                //unzip and overwrite FileRecord
                UnZipFile();
                //return myRecord
                return myRecord;
                 }
                 else return myRecord;
            }
            ...
            ...
        } 

现在,使用这些 FileRecords 和 ZippedFileRecords 的代码部分是用户可以在特定日期范围内获取所有 FileRecords 并获取屏幕上显示的信息的部分。由于 ZippedFileRecords 是压缩文件的代表,因此必须先解压缩它们。这是用于查找要显示的文件的代码部分:

public GetFrames(DateTime desiredStartTime, DateTime  desiredEndTime)
{
    for(int fileIdx = mFiles.Values.Count-1; fileIdx >= 0; --fileIdx)
    {
        FileRecord rec = (FileRecord)mFiles.GetByIndex(fileIdx);
        if(rec.StartTime>= desiredStartTime && rec.EndTime<=desiredEndTime)
        {
            ...
        }
        else
        {
            ...
        }
    }
}

导致我出现问题的线路FileRecord rec = (FileRecord)mFiles.GetByIndex(fileIdx);是有什么方法可以让我检查 mFiles[fileIdx] 是 ZippedFileRecord 还是 FileRecord 的天气?因为如果我能做到这一点,我可以只根据需要解压缩,而不是解压缩然后重新压缩可能数百个文件,每次它们要显示在屏幕上时,只有一两个实际适合用户的日期范围

4

6 回答 6

2

你可以做:

var zippedFileRecord = mFiles.GetByIndex(fileIdx) as ZippedFileRecord;

if (zippedFileRecord != null)
    ... do something with it

这样做会更干净:

foreach (var zippedFileRecord in mFiles.OfType<ZippedFileRecord>())
    ... do something with zippedFileRecord 

尽管通过向后浏览列表似乎您正在做一些特别的事情,但如果是这种情况,这将行不通。

但是像这样按类型过滤通常是一种代码味道。您可能应该添加一个虚拟GetFileRecord()方法以class FileRecord在该类中适当地实现它。然后覆盖它class ZippedFileRecord为该类做适当的事情。

然后,您只需在循环中调用该GetFileRecord()方法,而无需担心底层类型。

从外观上看,您对GetFileRecord()in的实现class FileRecord将是:

public virtual FileRecord GetFileRecord()
{
    return this;
}

并且其中的实现class ZippedFileRecord将与您已经编写的相同,但override添加到声明中:

public override FileRecord GetFileRecord()
{
    ...

然后你可以像这样使用它:

for(int fileIdx = mFiles.Values.Count-1; fileIdx >= 0; --fileIdx)
{
    FileRecord rec = ((FileRecord)mFiles.GetByIndex(fileIdx)).GetFileRecord();
    ...

最后一点:您为什么不使用泛型SortedList<TKey, TValue>以便可以使用强类型来避免强制转换?

于 2013-07-01T19:46:00.073 回答
1

你可以像这样测试它:

if(mFiles.GetByIndex(fileIdx) is ZippedFileRecord)
{
   ...
}
else if(mFiles.GetByIndex(fileIdx) is FileRecord)
{
   ...
}

请注意,您需要按此顺序检查它,因为 ZippedFileRecord 也是 FileRecord,但反之则不然。

于 2013-07-01T19:46:44.887 回答
1

使用is运算符 -

if(rec is ZippedFileRecord)
{
  //Unzip logic here
}
else
{

}

或者

GetFileRecord() virtual在文件记录类中制作方法并将override其放入ZippedFileRecord

public class FileRecord
{
    public virtual FileRecord GetFileRecord()
    {
       return this;
    } 
} 

public class ZippedFileRecord : FileRecord
{
    public override FileRecord GetFileRecord()
    {
       // Unzip and retunr FileRecord instance.
    } 
}

这样您就不必担心类型。这应该可以工作 -

FileRecord rec = mFiles.GetByIndex(fileIdx).GetFileRecord();
于 2013-07-01T19:46:51.250 回答
0

is你可以像这样使用运算符

if (!(rec is ZippedFileRecord)) 
{
   // do your stuff in case rec is not ZippedFileRecord
}
于 2013-07-01T19:46:26.490 回答
0

就个人而言,我想知道为什么 ZippedFileRecord::GetFileRecord 必须解压缩文件。由于您只需要元数据,因此我将重构该方法,以便在不解压缩文件的情况下设置元数据。然后,如果您确实需要文件数据本身,请解压缩文件。

于 2013-07-01T21:52:29.573 回答
0

您可以使用“is”来检查对象是否属于特定类型:

if (rec is ZippedFileRecord) {
    ...
}
else {
    ...
}

编辑:有关更多选项,请参阅此问题

于 2013-07-01T19:46:55.330 回答