区分两类
本文关键字:两类 | 更新日期: 2023-09-27 18:20:47
我有一个类FileRecord
和类public class ZippedFileRecord : FileRecord
,它们存储在具有所有FileRecords和ZippedFileRecords的SortedList mFiles
中。我遇到的问题是,我需要一种方法来区分两者,每个ZippedFileRecord都有一个FileRecord和一个名为GetFileRecord()的方法,在该方法中,它解压缩与ZippedFileRecords关联的文件,并为其创建一个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是Zipped文件的代表,因此必须首先对其进行解压缩。以下是用于查找要显示的文件的代码部分:
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吗?因为如果我能做到这一点,我只能根据需要解压缩,而不是每次在屏幕上显示时都解压缩数百个文件,只有一两个文件真正符合用户的日期范围
你可以做:
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
尽管通过向后浏览列表似乎你在做一些特别的事情,但如果是这样的话,这是行不通的。
但按类型过滤通常是一种代码味道。您可能应该向class FileRecord
添加一个虚拟GetFileRecord()
方法,以便在该类中适当地实现它。然后在class ZippedFileRecord
中重写它,为该类做适当的事情。
然后,您只需在循环中调用GetFileRecord()
方法,而无需担心底层类型。
从外观上看,GetFileRecord()
在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>
,以便使用强类型来避免强制转换?
您可以这样测试它:
if(mFiles.GetByIndex(fileIdx) is ZippedFileRecord)
{
...
}
else if(mFiles.GetByIndex(fileIdx) is FileRecord)
{
...
}
请注意,您需要按此顺序进行检查,因为ZippedFileRecord也是FileRecord,但不是相反。
使用is
运算符-
if(rec is ZippedFileRecord)
{
//Unzip logic here
}
else
{
}
或
使方法GetFileRecord()
virtual
在File记录类中,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();
您可以像这个一样使用is
运算符
if (!(rec is ZippedFileRecord))
{
// do your stuff in case rec is not ZippedFileRecord
}
您可以使用"is"检查对象是否为特定类型:
if (rec is ZippedFileRecord) {
...
}
else {
...
}
edit:有关更多选项,请参阅此问题。
就我个人而言,我想知道为什么ZippedFileRecord::GetFileRecord必须解压缩文件。由于您只需要元数据,我会重构该方法,以便在不解压缩文件的情况下设置元数据。然后,如果您确实需要文件数据本身,然后解压缩文件。