Mismatched behaviour between regular compiler and refactoringcompiler


W

Weeble

The included program compiles without errors, but produces an error
when you attempt to use a refactoring tool:

J:\TypeofTest\TypeofTest1\Program.cs(3,27): error CS0246: The type or
namespace name 'Bar' could not be found (are you missing a using
directive or an assembly reference?)

In addition, the syntax highlighter doesn't highlight the "Bar" in
"typeof(Bar)" as a class. If I replace that with "typeof(Foo.Bar)",
everything works as expected. What I don't understand is why there is
a difference. Should it be possible to implicitly reference an inner
class in an attribute like this (in which case it seems the
refactoring compiler is incorrect) or is it in fact not allowed (in
which case surely the regular compiler should say something)? I'm
using Visual Studio 2005.

using System.Diagnostics;

[DebuggerTypeProxy(typeof(Bar))]
public class Foo
{
public class Bar
{
private Foo m_foo;
public Bar(Foo foo) { m_foo = foo; }
}
}

class Program
{
static void Main() { }
}
 
Ad

Advertisements

W

Weeble

I've found a further problem. In the code that this example is derived
from, the equivalent to Bar is a private class. In that case, when I
change "typeof(Bar)" to "typeof(Foo.Bar)", I get a new error (again,
only from the refactoring compiler, not the regular one):

J:\TypeofTest\TypeofTest1\Program.cs(3,31): error CS0122: 'Foo.Bar' is
inaccessible due to its protection level

It seems it comes down to a question of whether or not the expression
for attribute constructors are evaluated inside or outside the scope
of the class. I should note that I'm using a private inner class in
large part because of this example here:

http://msdn2.microsoft.com/en-us/library/x810d419.aspx

Even so, I think it's cleaner to use a private inner class rather than
an internal top-level class, because there's really no need to make
the debug stuff visible to any other code.
 
W

Weeble

Which refactoring tool? The code is fine "as is" for regular C#...

Marc

Any of the built-in refactoring tools in Visual Studio 2005 seem to do
it for me. For example, right-click on "Program" (or any other
identifier) and choose "Refactor->Rename..." The output window will
switch to "Show output from: Refactor" and the error I described will
appear in it. The other symptom is the syntax highlighting, as I said.
If I have "typeof(Bar)" then "Bar" will appear black, whereas if I
have "typeof(Foo.Bar)", the "Foo.Bar" will appear teal, the colour
that indicates the name of a class.

I do have Visual Assist X installed, but I disabled it for these tests.
 
M

Marc Gravell

Verified (in VS2008) - interesting! But (in VS2008, at least) it is
purely cosmetic - the refactor still completes successfully (you just
get a yellow-triangle warning that it isn't happy, but once complete
it compiles fine; and so I couldn't say it is super-critical, unless
it actually stops VS2005 from completing the refactor [does it?]) .

I would suggest logging it via connect... http://connect.microsoft.com/VisualStudio
(if you do log it, post the url and I'll mark it as validated; or if
you don't already have a passport, I could log it on your behalf if
you like - but I won't do so without your nod).

Marc
 
Ad

Advertisements

W

Weeble

Yikes, that was an ordeal to get set up. I've submitted the bug here
(I think):https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx...

It got resolved "Won't Fix". Does that mean never? Seems a bit
disappointing. I tried to figure out which behaviour is correct, and
the best I could understand from the spec is that the refactoring
engine is correct and the regular compiler is wrong on the basis that
class members are only in scope inside the "class body", which
comprises everything between the curly braces, but not the attribute
specifiers. To be honest, that's not the behaviour I'd want, but I
couldn't see anything in there that would make me believe that either
attribute specifiers count as being in the class body, or that class
members are in scope anywhere except the class body or the class body
of a descendent class.

My workaround is to implement DebuggerTypeProxy classes as inner
classes with internal instead of private access, and to use fully
qualified names when constructing the attributes. That way both the
refactoring engine and the regular compiler seem happy. I wouldn't
like the refactoring engine to be spitting out lots of errors whenever
a colleague attempts to use it, even if I know it shouldn't actually
prevent it from working.
 
M

Marc Gravell

I'd need to look closely at the spec to figure which behavior is
correct; I would presume the regular compiler, but it could go either
way... however, I can see their view that it isn't eactly critical
(purely cosmetic, and purely during refactoring). But yes: sometimes
it can be frustrating when you see "won't fix"; I've had "won't fix"
with critical runtime issues in things like WSE, and even something as
simple (yet commonplace) as the runtime not being able to sort strings
correctly [genuinely!]. But sometimes things do get fixed... oh well.

Marc
 
W

Weeble

I'd need to look closely at the spec to figure which behavior is
correct; I would presume the regular compiler, but it could go either
way... however, I can see their view that it isn't eactly critical
(purely cosmetic, and purely during refactoring). But yes: sometimes
it can be frustrating when you see "won't fix"; I've had "won't fix"
with critical runtime issues in things like WSE, and even something as
simple (yet commonplace) as the runtime not being able to sort strings
correctly [genuinely!]. But sometimes things do get fixed... oh well.

A few hours later there was a comment explaining the reasoning. I
totally understand that it's not worth going to the bother of changing
the refactoring engine in 2005 or 2008 for something quite minor. I
am, however, worried by the idea that the problem could be in the
regular compiler. To me, that would be quite serious. I'm hoping that
someone who understands the spec better than I do might explain it to
me.

As I understand it, based on the C# Spec V3, the "scope" of a class
member (i.e. the places it can be used without "Class.Member"
qualification) is the "class-body" of that class and of any
subclasses. (§3.7) The "accessibility domain" of a private class
member (i.e. the places it can be accessed from at all) are the
"program text" of the class, which is itself defined as the "class-
body". (§3.5.2) The "class-body" is defined as being everything
between the { curly braces } of the class, which does not include
attribute specifiers.

I sure do hope my interpretation is wrong!
 
J

Jon Skeet [C# MVP]

As I understand it, based on the C# Spec V3, the "scope" of a class
member (i.e. the places it can be used without "Class.Member"
qualification) is the "class-body" of that class and of any
subclasses. (§3.7) The "accessibility domain" of a private class
member (i.e. the places it can be accessed from at all) are the
"program text" of the class, which is itself defined as the "class-
body". (§3.5.2) The "class-body" is defined as being everything
between the { curly braces } of the class, which does not include
attribute specifiers.

I sure do hope my interpretation is wrong!

Well, your logic certainly sounds right to me. However, it could just
be another case where the bug is actually in the spec - that the
current behaviour is the designed one, but the design wasn't correctly
described in the spec. I think it's as likely that there'll be a spec
change to fix this as a compiler change (especially as fixing the spec
to mirror reality isn't a breaking change; fixing the compiler to
mirror the spec certainly would be).

Another one to ask the team, I guess...

Jon
 
Ad

Advertisements

J

Jon Skeet [C# MVP]

Another one to ask the team, I guess...

Here's the reply:

<quote>
This certainly looks like an error in the specification. I'll see what
we can do about getting it fixed. Thanks for bringing it to our
attention.
</quote>
 
Ad

Advertisements


Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top