【发布时间】:2020-07-31 10:15:33
【问题描述】:
- 有什么问题?
我正在处理一个更大的项目,其中包含大量代码(.Net 4.5),但我会尝试向您提供我目前对该问题的概述。我试图搜索类似的问题但没有成功(抱歉,如果它是重新发布的)。
项目 A(类库)
namespace nameA
{
public interface ILog
{
bool GetFile(string a, string b, bool c);
bool SetFile(string d);
}
}
项目 B(类库) - 取决于项目 A
using nameA;
namespace nameB
{
public class ImplementInterface : ILog
{
// implementation of the interface + other methods
}
}
项目C(类库)依赖于projectA和projectB
using nameA;
using nameB;
namespace nameC
{
public class SomeClass : IDisposable
{
public ImplementInterface _implementation { get; }
public SomeClass()
{
_implementation = new ImplementInterface()
}
// unrelated implementation code ...
private method Start()
{
ILog tmp = _implementation; // -> error CS0266: Cannot implicitly convert type 'nameB.ImplementInterface' to 'nameA.ILog'
// ILog tmp = (ILog)_implementation; -> this will compile but it fails during runtime (usage of 'as' returns null)
}
}
}
从上面的示例中可以看出,由于从子类到接口的转换,代码无法编译。
如果我在同一个项目中执行此示例,一切都会编译并且代码可以正常工作,如果我在 projectB 和 nameB 命名空间中实现 SomeClass 也可以正常工作。我不明白为什么它不起作用。
- 按照我的尝试:
- 检查是否有任何其他 ILog 或 ImplementInterface 实现,以便名称解析成为问题 -> 没有找到
- 检查程序集名称和版本(以便在运行 projectC 时使用正确的程序集)-> 似乎没问题
- 检查所有程序集是否已加载 -> 是的,它们已加载
- 使用反射检查ImplementInterface内部的接口方法->方法似乎在那里,反射可以找到类内部的接口实现。
- 在项目 B 和 nameB 中实现 SomeClass -> 似乎问题已经消失了,但它并没有回答为什么首先出现问题的问题?
- 假设
- 好吧,我已经阅读了有关协方差逆变的信息,但我认为这在这里不会发挥任何作用
- 我认为这是关于名称解析或 dll 加载的一些小问题
我对这个代码库不太熟悉,所以它也可能是我错过的东西,但现在我不知道是什么?
编辑: 当时我没有正确理解这个问题。这是上面代码不起作用的根本原因的小描述。
上面的项目 B 表单包含一个实现接口 ILog 的类 ImplementInterface,还使用了 ILMerge 工具(一个 .NET 静态链接器库) ILMerge 将 ProjectA 中的所有代码(连同项目 A 中的接口)放到 .dll来自项目 B。 由于项目 C 也使用了项目 A 和项目 B,因此 ILog 接口被实现了两次,编译器拒绝编译该接口并出现错误(错误 CS0266:无法隐式转换类型)。当我打印出所有使用过的程序集时,由于 ILMerge 将项目 A 的程序集合并到项目 B 中,因此没有显示两次。
【问题讨论】:
-
我们不希望您发布大量代码。但我们确实要求您创建一个minimal reproducible example。学习创建一个的事情之一是它本身就是一种有价值的调试技术。
-
非复制。您可以将派生类型分配给基类型的变量。如果
ImplementInterface : ILog,您可以将ImplementInterface实现类型的实例分配给ILog类型的变量。 -
感谢大家的帮助,当时我没有正确理解问题,所以我的问题无效。检查上面的编辑,看看真正的问题出在哪里。问题现已解决。