【发布时间】:2019-01-03 22:26:18
【问题描述】:
我的问题的前提,用简单的英语:
- 名为
Foo的库依赖于名为Bar的库 - Foo 中的类扩展 Bar 中的类
- Foo 定义了简单地传递给 Bar 的属性/方法
- 应用程序
FooBar,仅依赖于 Foo
考虑以下示例:
class Program
{
static void Main(string[] args)
{
Foo foo = Foo.Instance;
int id = foo.Id; // Compiler is happy
foo.DoWorkOnBar(); // Compiler is not happy
}
}
Foo定义如下
public class Foo : Bar
{
public new static Foo Instance { get => (Foo)Bar.Instance; }
public new int Id { get => Bar.Id; }
public void DoWorkOnBar()
{
Instance.DoWork();
}
}
条形定义如下
public class Bar
{
public static Bar Instance { get => new Bar(); }
public static int Id { get => 5; }
public void DoWork() { }
}
完全难倒我的部分:
没有引用 Bar 库
-
FooBar可以检索Bar提供的ID(或者至少它可以编译) -
FooBar不能 要求 Foo 完成最终由Bar完成的工作
与foo.DoWorkOnBar();相关的编译器错误是
“Bar”类型是在未引用的程序集中定义的。您必须添加对程序集 'Bar, Version 1.0.0.0, Culture=Neutral, PublicKeyToken=null' 的引用。
为什么编译器会出现差异?
如果没有 FooBar 添加对 Bar 的引用,我会假设这些操作都不会编译。
【问题讨论】:
-
因为属性是直接在 foo 上定义的,所以编译器很高兴。但是当你想使用 Instance.DoWork() 并且 DoWork 定义在 bar 上时,编译器需要知道它在哪里可以找到那个 DoWork 方法。因此它需要对 bar 的引用
-
如果您将实现减少到
public class Bar { }和public class Foo : Bar { public static Foo Instance => null; public int Id => 42; public DoWorkOnBar() { } },问题是否仍然存在?疯狂猜测:方法可以重载而属性不能重载是有原因的。 -
可用于重现问题的最小
Foo是public class Foo : Bar { public static int P => 0; public static int M() => 0; }。调用Foo.P没问题;调用Foo.M()会使编译器对Bar产生强烈要求。为什么?现在这可能需要编译器作者进一步解释。 (但@PetSerAl 对“责备重载解决方案”的猜测是安全的,因为这是迄今为止语言中最复杂的部分,并且有很多有趣的阴暗角落。) -
@Matt 我建议你 edit 你的问题并将
Foo和Bar实现减少到最小的必要版本来重现错误,所以其他人不会因为额外的问题而陷入错误的轨道分心。 -
感谢这个绝妙的问题。很难找到这个,因为甚至很难找到问题:D
标签: c# compiler-errors dependencies dependency-management