2

I have a class FileRecord and the class public class ZippedFileRecord : FileRecord, that get stored in SortedList mFiles which has all the FileRecords and ZippedFileRecords. The issue I'm running into is that I need a way to differentiate between the two, each ZippedFileRecord has a FileRecord and a method called GetFileRecord() where it unzips the file associated with ZippedFileRecord and makes a FileRecord for it (as seen in the chunk below..)

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

now the portion of code that uses these FileRecords and ZippedFileRecords is something that a user can grab all the FileRecords in a certian date range, and get the info for those displayed on screen. Since ZippedFileRecords are representative of Zipped Files they must first be unzipped. here is the portion of code used to seek out the files to be displayed:

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
        {
            ...
        }
    }
}

The Line that is causing me issues is FileRecord rec = (FileRecord)mFiles.GetByIndex(fileIdx); is there any way for me to check weather the mFiles[fileIdx] is a ZippedFileRecord or a FileRecord? because If I can do that I can unzip only as needed instead of unzipping and then rezipping potentially hundreds of Files every time they are to display on screen only to have one or two actually fit in the user's date range

Medic3000
  • 786
  • 4
  • 20
  • 44

6 Answers6

2

You can do:

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

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

It would be cleaner to do:

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

Although it seems that that you are doing something special by going backwards through the list, so this wouldn't work if that's the case.

But filtering by type like that is often a code smell. It may be that you should add a virtual GetFileRecord() method to class FileRecord implement it appropriately in that class. Then override it in class ZippedFileRecord to do the appropriate thing for that class.

Then you just call the GetFileRecord() method in the loop without needing to worry about the underlying type.

From the look of it, your implementation of GetFileRecord() in class FileRecord would simply be:

public virtual FileRecord GetFileRecord()
{
    return this;
}

And the implementation in class ZippedFileRecord would be the same as the one you already wrote, but with override added to the declaration:

public override FileRecord GetFileRecord()
{
    ...

Then you could use it like this:

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

One last point: Why aren't you using the generic SortedList<TKey, TValue> so that you can use strong types to avoid casting?

Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
1

You can test it like this:

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

Note, that you need to check it in this order, since a ZippedFileRecord is also a FileRecord, but not vice versa.

Romano Zumbé
  • 7,893
  • 4
  • 33
  • 55
1

Use the is operator -

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

}

OR

Make the method GetFileRecord() virtual in File record class and override it in ZippedFileRecord

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

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

This way you don't have to worry for the type. This should work then -

FileRecord rec = mFiles.GetByIndex(fileIdx).GetFileRecord();
Rohit Vats
  • 79,502
  • 12
  • 161
  • 185
0

You could use is operator like this

if (!(rec is ZippedFileRecord)) 
{
   // do your stuff in case rec is not ZippedFileRecord
}
Claudio Redi
  • 67,454
  • 15
  • 130
  • 155
0

You can use "is" to check if an object is of a specific type:

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

edit: See this question for more options.

Community
  • 1
  • 1
Matthias
  • 1,005
  • 7
  • 20
0

Personally, I'm wondering why ZippedFileRecord::GetFileRecord has to unzip the file. Since you only want the metadata, I'd refactor the method so that the metadata is set up without unzipping the file. Then, if you actually need the file data itself, then unzip the file.

Eric Brown
  • 13,774
  • 7
  • 30
  • 71