16

In the watch window, I'm trying to look at TaskScheduler.Current, but it shows me the following error:

The type 'System.Threading.Tasks.TaskScheduler' exists in both 
'CommonLanguageRuntimeLibrary' and 'System.Threading.dll'   

This is true for my program since:

  • This is a .NET 4.0 exe which uses the TaskScheduler out of mscorlib (CommonLanguageRuntimeLibrary)
  • A dll is brought in through late binding which references an old Reactive Extensions .NET 3.5 System.Threading.dll which also has TaskScheduler in the same namespace.

Question: What syntax can I use in the debugger to specify the dll of the TaskScheduler I want to inspect?

As an aside: I assume there is no issue (i.e. no undefined behavior) in terms of having these two identically named types being brought into the same executable, right?

Matt Smith
  • 17,026
  • 7
  • 53
  • 103
  • 4
    Interesting problem! There shouldn't be any ambiguity; references to types are all qualified by containing assembly. But I don't know if there's any way to qualify references in the debugger... – anton.burger Apr 08 '13 at 16:43

1 Answers1

5

I'm not sure if this works through the watch window (but I don't see why it shouldn't, who knows) - but the way to disambiguate between two dll-s with same types is using extern alias.

That's the same thing as the global:: - except that in this case you can use to specify dll aliases.

You can use it by setting / defining alias yourself on the dll reference (I think there is alias field there in the properties).

two different DLL with same namespace

I'm not sure if this entirely applies to your case, i.e. if you are able to do that, but you'll have to try it out in your own case.

EDIT: (based on the comments)

Given specifics - I tried it in my debugger. Since the other one is late-binding - compiler doesn't know about it (of course, as it wouldn't work).

So in your source code (.cs where you need to do the watch anyway) add at the top e.g.

using mysystem = global::System.Threading.Tasks.TaskScheduler;  

Then in the watch mysystem.Current (I'm basing it on my example)

Or...

using mytasks = global::System.Threading.Tasks;  

and mytasks.TaskScheduler - doesn't matter really which one really.

EDIT2:
And for historical reasons - I kind of confirmed that code-editing is unavoidable.

1) remove mscorlib from the project - project, setting, build, advanced.

2) unload and edit project configuration manually - add the mscorlib reference (adding through VS is not allowed). Also another fix is required for WPF apps (out of scope here),

3) add aliases for mscorlib - you can add multiple ones, separate w/ ,, that works fine,

4) add extern alias <your alias>,

from that point you can reference it in debugger - but there is not way of forgoing the manual code editing. Also extern alias is per 'building unit', i.e. file, so nothing global.

In short, that's the best we could do, IMHO.


And a confirmation from @JaredPar on this
How can I qualify a .NET type with assembly name for Visual Studio debugger to disambiguate while using an ambiguous type?

Community
  • 1
  • 1
NSGaga-mostly-inactive
  • 14,052
  • 3
  • 41
  • 51
  • I don't have any `extern alias`. I directly reference mscorlib. System.Threading.dll comes in through late binding. With that in mind, it's not clear what your suggesting I type into the watch window to disambiguate. – Matt Smith Apr 08 '13 at 20:20
  • try `global::` - you can do the following in the code at least `var current = global::System.Threading.Tasks.TaskScheduler.Current;`. I still have no idea if the other dll will interfere with that. – NSGaga-mostly-inactive Apr 08 '13 at 20:25
  • Ah, I see. okay, I tried `global::System.Threading.Tasks.TaskScheduler`, but I get the same error message. Which makes sense to me because they are both in the global namespace (since they weren't brought in via an `extern alias`) – Matt Smith Apr 08 '13 at 20:39
  • 1
    ok, will get there :) - here is another one - I tried it in my debugger. Since the other one is late-binding - compiler doesn't know about it (of course, as it wouldn't work). So in your source code (.cs where you need to do the watch anyway) add at the top e.g. `using mysystem = global::System.Threading.Tasks.TaskScheduler;`. Then in the watch `mysystem.Current` (I'm basing it on my example). – NSGaga-mostly-inactive Apr 08 '13 at 20:48
  • Or `using mytasks = global::System.Threading.Tasks;` and `mytasks.TaskScheduler` - doesn't matter really - that's matter of preference now. – NSGaga-mostly-inactive Apr 08 '13 at 20:51
  • That works, thanks! +1 for a good work-around. Unfortunately, it means (a) I have to temporarily modify code to do my debugging and (b) I have to have in my call-stack a source file that has a `using` like this. This won't be possible, generally, when I don't have the luxury of changing the source. – Matt Smith Apr 08 '13 at 21:00
  • I understand that - problem is w/ `mscorlib` which is silently added (we can exclude it, but not sure if that'd help) - it doesn't seem possible putting an `alias` on it - which is the key here. Otherwise compilers are pretty 'predictable animals' and there's always some way to do things you need. – NSGaga-mostly-inactive Apr 08 '13 at 21:11
  • 2
    @MattSmith I think working around it as detailed in this answer is the closest you're going to get. I found a [similar question about the Immediate window](http://stackoverflow.com/questions/1571958/how-can-i-qualify-a-net-type-with-assembly-name-for-visual-studio-debugger-to-d/1572988?noredirect=1#comment22664215_1572988), and got a pretty definitive answer from JaredPar. – anton.burger Apr 09 '13 at 22:28
  • @shambulator - I had another go at it yesterday (edited in just now), and it confirms what we know - I just didn't think it was valuable to add (as there is no solution w/o editing) – NSGaga-mostly-inactive Apr 09 '13 at 22:52
  • @shambulator Thanks for linking in that other question, I hadn't found that. @ NSGaga, thanks for the additions. – Matt Smith Apr 10 '13 at 01:44