我的问题如下。我为一个显然不起作用的家庭项目做了代码设计。也许你可以帮我弄清楚“代码味道”的来源。
好的,让我们开始吧: 我已经定义了一些类来包装不同类型的存档类型:
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);
}
具体的,实际上实现特定的behaiour:
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'
据我所知,泛型参数不能被隐含地转换。有没有办法解决这个问题?这个代码/设计“闻”了吗?
非常感谢你。
答案 0 :(得分:2)
您可以使用逆变接口而不是不实现任何功能的抽象类。在这种情况下,您只能将type参数用作方法的返回值,而不能用作参数:
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)
{
// ...
}
}
答案 1 :(得分:0)
我通过使用c#.NET 4.0的“dynamic”关键字找到了另一种方法......
class Program
{
static void Main(string[] args)
{
dynamic archiveManager = null;
if (/*some condition*/) {
archiveManager = new ZipArchiveManager();
}
else {
archiveManager = new TarArchiveManager();
}
}
}
对我来说就像一个魅力;)