DonBoitnott
DonBoitnott

Reputation: 11025

Why am I getting this definition reference error?

I am using TaskBar methods defined within the namespace Microsoft.WindowsAPICodePack.Taskbar. Specifically, I'll focus on SetProgressState for this question.

Here is the meta-definition I get when I ask for the definition of 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);
    }
}

Obviously, I have omitted most of that class's definition just to highlight the one method's overloads.

To this point, I have been using the single-parameter overload and have had no issues. However, today I attempted to use the two-parameter overload that accepts an IntPtr as its second parameter.

When I did that, I started getting this error during build:

The type 'System.Windows.Window' is defined in an assembly that is not referenced. You must add a reference to assembly 'PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'

So my question is why I did not get an error for using the single-parameter overload, but I do get an error for referencing one of the others (and for the wrong one)?

Edit (for addition sub-question):

I also tried the following, which made no difference:

SetProgressState(myState, (IntPtr) myWindowHandle);

I thought that by casting explicitly, I would avoid the compiler confusion in realizing the appropriate overload, but that was not the case.

Upvotes: 5

Views: 1628

Answers (2)

Shaz
Shaz

Reputation: 1396

I'll expand my comments here for clarity. Your project isn't able to find System.Windows.Window. I mispoke in my comment when I said you need to put in:

using System.Windows;

To the file.

Instead, the project needs to have a reference to System.Windows. The reference you want is given to you in the error message: PresentationFramework. You will also need to include PresentationCore(a similar error will pop up telling you to add a reference to PresentationCore).

The type 'System.Windows.Window' is defined in an assembly that is not referenced. You must add a reference to assembly 'PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'

Upvotes: 1

anthonyvd
anthonyvd

Reputation: 7590

According to the MSDN page on Overload Resolution, the compiler will start by selecting the potential candidates

Each of these contexts defines the set of candidate function members and the list of arguments in its own unique way

then, the best target is selected:

If the set contains only one function member, then that function member is the best function member.

My understanding here is that the compiler doesn't even consider the 2 arguments methods when you call it with 1 argument. However, when you use the 2 arguments version, it needs information about the argument types. In this case, it needs to know what System.Windows.Window is to be able to determine which overload you want to call.

Example

Imagine you have 2 classes in separate Class Libraries

class Foo
{

}

class Bar : Foo
{

}

and 4 methods in an other library

static void Do()
{

}

static void Do(Foo foo)
{

}

static void Do(Bar bar)
{

}

static Foo Get()
{
    return new Bar();
}

You reference the Methods Library and the Library Containing Foo, but not the library containing Bar.

Then, in your application, you obtain an object of type Foo from the Methods Library (it could be a Bar too, but you don't know). How is the compiler supposed to resolve an eventual call to Do() with arguments?

It can't unless it has the type information for Bar as well.


As for your subquestion, it's a result of the above plus the fact that a cast doesn't necessarily force an overload to be chosen. Let's imagine that System.Windows.Window derives from IntPtr for a moment. Casting the argument to IntPtr doesn't help the compiler resolve the overload at all (see above example).

Since the type information is not present, the compiler emits an error because it can't know for sure. Honestly, for compilers, that's a feature.

Upvotes: 3

Related Questions