my problem is the following. I have made a code design for a home project which is apparently not working. Maybe you can help me to figure out where the "code smell" comes from.
Ok let's start: I have defined some classes to wrap around different kind of archive types:
public abstract class Archive { }
public class ZipArchive : Archive { }
public class TarArchive : Archive { }
To handle with those archives, I defined Manager classes. An abstract one that defines the needed behaviour,
public abstract class ArchiveManager<T> where T : Archive
{
public abstract void OpenArchive(T archive);
}
And the concrete ones, that actually implement the specific behaiour:
public class ZipArchiveManager : ArchiveManager<ZipArchive>
{
public override void OpenArchive(ZipArchive archive) { /* .. */ }
}
public class TarArchiveManager : ArchiveManager<TarArchive>
{
public override void OpenArchive(TarArchive archive) { /* .. */ }
}
What happens now is that during compile time, I dont know which kind of archives I will process, so I tried the following:
class Program
{
static void Main(string[] args)
{
ArchiveManager<Archive> archiveManager = null;
if (/*some condition*/) {
archiveManager = new ZipArchiveManager();
}
else {
archiveManager = new TarArchiveManager();
}
}
}
which ended up in the following error:
Cannot implicitly convert type 'ZipArchiveManager' to 'ArchiveManager'
As far as I understand, the generic argument cannot be implicitely converted. Is there any way to come around this? Does this code / design "smell"?
Thank you very much in advance.
You can use a contravariant interface instead of an abstract class that doesn't implement any functionality. In this case, you can only use the type parameter as a return value of a method, not as an argument:
public interface IArchiveManager<out T>
where T : Archive
{
T OpenArchive(Stream stream);
}
Then, simply implement the interface in your manager classes:
public class ZipArchiveManager : IArchiveManager<ZipArchive>
{
public ZipArchive OpenArchive(Stream stream)
{
// ...
}
}
public class TarArchiveManager : IArchiveManager<TarArchive>
{
public TarArchive OpenArchive(Stream stream)
{
// ...
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With