5

我的问题如下。我为一个显然不起作用的家庭项目进行了代码设计。也许您可以帮助我弄清楚“代码气味”的来源。

好的,让我们开始吧:我已经定义了一些类来包装不同类型的存档类型:

public abstract class Archive { }
public class ZipArchive : Archive { }
public class TarArchive : Archive { }

为了处理这些档案,我定义了 Manager 类。定义所需行为的抽象行为,

public abstract class ArchiveManager<T> where T : Archive
{ 
    public abstract void OpenArchive(T archive);
}

而具体的,实际上实现了特定的行为:

public class ZipArchiveManager : ArchiveManager<ZipArchive>
{
    public override void OpenArchive(ZipArchive archive) {  /* .. */ }
}

public class TarArchiveManager : ArchiveManager<TarArchive>
{
    public override void OpenArchive(TarArchive archive) {  /* .. */ }
}

现在发生的情况是,在编译期间,我不知道我将处理哪种档案,所以我尝试了以下方法:

class Program
{
    static void Main(string[] args)
    {
        ArchiveManager<Archive> archiveManager = null;

        if (/*some condition*/) {            
            archiveManager = new ZipArchiveManager();
        }
        else {
            archiveManager = new TarArchiveManager();
        }
    }
}

最终出现以下错误:

无法将类型“ZipArchiveManager”隐式转换为“ArchiveManager”

据我了解,泛型参数不能被隐式转换。有什么办法可以解决这个问题吗?这个代码/设计“有味道”吗?

非常感谢您提前。

4

2 回答 2

2

您可以使用逆变接口代替不实现任何功能的抽象类。在这种情况下,您只能将类型参数用作方法的返回值,而不能用作参数:

public interface IArchiveManager<out T>
    where T : Archive
{
    T OpenArchive(Stream stream);
}

然后,只需在管理器类中实现接口:

public class ZipArchiveManager : IArchiveManager<ZipArchive>
{
    public ZipArchive OpenArchive(Stream stream)
    {
        // ...
    }
}

public class TarArchiveManager : IArchiveManager<TarArchive>
{
    public TarArchive OpenArchive(Stream stream)
    {
        // ...
    }
}
于 2012-04-15T10:10:19.430 回答
0

我通过使用 c# .NET 4.0 的“动态”关键字找到了另一种方法......

class Program
{
    static void Main(string[] args)
    {
        dynamic archiveManager = null;

        if (/*some condition*/) {            
            archiveManager = new ZipArchiveManager();
        }
        else {
            archiveManager = new TarArchiveManager();
        }
    }
}

对我来说就像一个魅力;)

于 2012-04-29T23:46:58.460 回答