为什么我会收到此定义引用错误?

Don*_*ott 5 .net c# compiler-construction compiler-errors

我正在使用TaskBar名称空间中定义的方法Microsoft.WindowsAPICodePack.Taskbar。具体来说,我将重点关注SetProgressState这个问题。

这是当我询问 的定义时得到的元定义SetProgressState

namespace Microsoft.WindowsAPICodePack.Taskbar
{
    public class TaskbarManager
    {
        public void SetProgressState(TaskbarProgressBarState state);
        public void SetProgressState(TaskbarProgressBarState state, IntPtr windowHandle);
        public void SetProgressState(TaskbarProgressBarState state, System.Windows.Window window);
    }
}
Run Code Online (Sandbox Code Playgroud)

显然,我省略了该类的大部分定义,只是为了突出显示一个方法的重载。

到目前为止,我一直在使用单参数重载并且没有遇到任何问题。IntPtr然而,今天我尝试使用接受 an作为第二个参数的双参数重载。

当我这样做时,我在构建过程中开始收到此错误:

类型“System.Windows.Window”是在未引用的程序集中定义的。您必须添加对程序集“PresentationFramework,Version=3.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35”的引用

所以我的问题是为什么我没有因使用单参数重载而收到错误,但我确实因引用其他参数之一(以及错误的参数)而收到错误?

编辑(用于添加子问题):

我还尝试了以下方法,但没有什么区别:

SetProgressState(myState, (IntPtr) myWindowHandle);
Run Code Online (Sandbox Code Playgroud)

我认为通过显式转换,我可以避免编译器在实现适当的重载时出现混乱,但事实并非如此。

Ant*_*ois 3

根据MSDN 上关于重载解析的页面,编译器将首先选择潜在的候选者

每个上下文都以自己独特的方式定义候选函数成员集和参数列表

然后,选择最佳目标:

如果该集合仅包含一个函数成员,则该函数成员是最佳函数成员。

我的理解是,当您使用 1 个参数调用它时,编译器甚至不会考虑 2 个参数方法。但是,当您使用 2 个参数版本时,它需要有关参数类型的信息。在这种情况下,它需要知道什么System.Windows.Window才能确定您要调用哪个重载。

例子

假设您在不同的类库中有 2 个类

class Foo
{

}

class Bar : Foo
{

}
Run Code Online (Sandbox Code Playgroud)

以及其他库中的 4 个方法

static void Do()
{

}

static void Do(Foo foo)
{

}

static void Do(Bar bar)
{

}

static Foo Get()
{
    return new Bar();
}
Run Code Online (Sandbox Code Playgroud)

您引用了方法库和包含的库Foo,但不引用包含的库Bar

然后,在您的应用程序中,您Foo从方法库中获取一个类型的对象(也可能是 aBar类型,但您不知道)。编译器应该如何解决Do()带参数的最终调用?

除非它也具有 Bar 的类型信息,否则它不能。


至于您的子问题,这是上述结果加上强制转换不一定强制选择重载这一事实的结果。让我们想象一下这System.Windows.Window源自IntPtr于片刻。将参数转换为IntPtr根本无法帮助编译器解决重载问题(请参见上面的示例)。

由于类型信息不存在,编译器会发出错误,因为它无法确定。老实说,对于编译器来说,这是一个功能。