问题描述
我遇到了一个我刚刚注意到的奇怪问题.
I've come across a strange issue that I've just now noticed.
如果您有 3 个项目的解决方案
If you have a solution with 3 projects
** 注意讨论后编辑**
** NOTE Edited after discussion **
项目 LibA - 有一个 ClassA
Project LibA - Has a ClassA
namespace LibA
{
public class ClassA
{
public override string ToString()
{
return "The logic in class A!";
}
}
}
项目 LibB - 有一个 ClassB
Project LibB - Has a ClassB
using LibA;
namespace LibB
{
public class ClassB
{
public ClassA a;
public ClassB()
{
a = new ClassA();
}
public object Foo()
{
return a;
}
}
}
项目 LibC - 有一个 ClassC
Project LibC - Has a ClassC
using LibB;
namespace LibC
{
public class ClassC
{
public ClassB b;
public ClassC()
{
b = new ClassB();
}
public object Foo()
{
return b.Foo();
}
}
}
终于有试驾了
using System;
using LibC;
namespace Shell
{
class Program
{
static void Main(string[] args)
{
ClassC c = new ClassC();
Console.WriteLine(c.Foo());
}
}
}
现在,如果您编译它,一切都会完美运行.如果您检查 LibC 的二进制文件夹的内容,您会看到它自动滚动通过依赖链以确定它需要拉入 LibA 和 LibB
Now if you compile this, everything will work perfectly. If you examine the contents of LibC's binary folder, you'll see that it automatically rolled through the chain of dependencies to determine that it needed to pull in LibA and LibB
但是,如果您将 ClassB 更改为从 A 类继承比如
However, if you alter ClassB to inherit from class A such as
using LibA;
namespace LibB
{
public class ClassB : ClassA
{
ClassA a;
}
}
尝试编译,会报错
错误 2 类型LibA.ClassA"在未引用的程序集中定义.您必须添加对程序集LibA,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null"的引用.
Error 2 The type 'LibA.ClassA' is defined in an assembly that is not referenced. You must add a reference to assembly 'LibA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.
** 原始问题**
有谁知道为什么(无论是 msbuild 还是 Visual Studio)当 ClassA 是 ClassB 的成员时引用 LibA 足够聪明,但是当 ClassA 是 ClassB 的基类时引用 LibA 不够聪明?
Does anyone know why (whether it is msbuild or visual studio) it is smart enough to reference LibA when ClassA a member of ClassB, but it isn't smart enough to reference LibA when ClassA is the base class of ClassB?
我知道这很挑剔,但我真的很感激一些一致的行为
I know it's nitpicky, but I would really appreciate some consistent behavior
** 用这些观察到的测试修正了问题 **
** Amended Question with these observed tests **
我听说有些人将其定义为直接"或间接"引用.然而,直接显然不仅仅是可见性范围,它似乎是一种类型的继承和实际使用.
I'm hearing what some define as "direct" or "indirect" references. However, direct is clearly not just the visibility scoping, it seems to be inheritance and actual usage of a type.
在没有继承的情况下,测试驱动程序足够聪明,可以解析并自动引用 LibA、LibB 和 LibC.
Without inheritance, the test driver is smart enough to resolve and automatically reference LibA, LibB and LibC.
在 ClassB 中有一个可见的 public 成员 ClassA,但仅此一项不会产生编译/链接错误.
There is a public member ClassA visible in ClassB and yet that alone doesn't produce the compilation/linking error.
调试器肯定会从测试驱动程序中解析 ClassA,因此它清楚地加载了正确的程序集.
The debugger definitely resolves ClassA from the test driver, so it clearly loaded the correct assembly.
所以考虑到所有这些.我现在得到了整个直接"和间接"的东西.
So with all that in mind. I get the whole "direct" and "indirect" stuff now.
为什么链接器/编译器/IDE 至少不尝试在直接"场景中自动引用被引用库的依赖项?知道存在依赖关系并在间接"场景中引用它们显然足够聪明.
The thing that is still not clicking to me why the linker/compiler/IDE doesn't at least try to automatically reference the dependencies of a referenced library in an "direct" scenario? It's clearly smart enough to know the dependencies are there and reference them in an "indirect" scenario.
推荐答案
这是一致的行为.第一个是简单的引用,第二个是继承.
This is consistent behaviour. The first one is a simple reference, the second one is inheritance.
如果一个程序集被编译并且一个类从另一个程序集中的一个类继承,则需要该引用来构造它.
If an assembly is compiled and a class inherits from a class in another assembly, that reference is required to construct it.
LibB
只包含ClassB
的类定义中添加 的信息,它不会从 LibA 中复制所有内容
(如果 LibA
被更新并且 ClassA
被改变,这将产生不一致的代码,LibB
仍然包含旧信息).
LibB
only contains the information that is added in the class definition of ClassB
, it doesn't copy everything from LibA
(this would produce inconsistent code if LibA
is updated and ClassA
is changed while doing that, LibB
would still contain the old information).
所以要在 LibC
中使用继承的类定义,它需要来自 LibA
(对于 ClassA
)和 LibB 的信息
(ClassB
) 来构造它,因此需要直接引用 LibA
.
So to use an inherited class definition in LibC
, it needs both the information from LibA
(for ClassA
) and LibB
(ClassB
) to construct it, thus a direct reference to LibA
is needed.
在示例中,对不同程序集的类的所有引用都是私有的,因此只需要下一级(ClassC
不需要知道 ClassA
在那里不是该类的直接用法).如果在 ClassB
中使用的 ClassA
是公共字段或属性,则 ClassC
将直接引用 ClassA
并且还需要直接引用该类定义(从 LibC
引用 LibA
).
In the example, all references to classes of different assemblies are private, thus only the next level is neeed (ClassC
doesn't need to know about ClassA
as there is no direct usage of that class). If the usage of ClassA
in ClassB
was a public field or propety, ClassC
would have a direct reference to ClassA
and would need a direct reference to that class definition as well (reference to LibA
from LibC
).
在不同的形式中,继承示例也是如此.ClassC
直接引用了 ClassA
(由于 ClassB
继承自 ClassA
),因此引用了声明构建完整的类定义需要程序集(即 LibA
).
In a different form, this is also the case in the inheritance example. ClassC
has a direct reference to ClassA
(due to ClassB
inherting from ClassA
), thus a reference to the declaring assembly (namely LibA
) is needed to construct the full class definition.
这篇关于.Net Inheritance - 自动依赖引用行为问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!