Why does this work?

S

Scott M.

This is exactly what I'm saying. In your first example, color.AliceBlue is
simply using the shared readonly property of the Color class - - business as
usual and no problem.

-Scott
 
S

Scott M.

You are saying that color.AliceBlue refers to the _type_ color, right?
Then
this line must not work because 'R' is an instance member:

sub x(byval color as color)
dim b as byte = color.R
end sub

Though, it is compilable. Obviously there seems to be a contradiction in
in
the compiler's behavior, IMO. - strangely not on each of Bob's machines,
whyever.

No contradiction. This works because this time you are accessing the R
property of the instance of Color that would have to have been made by the
calling procedure, which is perfectly accepatable. What you've left out is
what the calling procedure would look like:

Sub test()
Dim c As Color = Color.FromName("SlateBlue")
x(c)
End Sub

Obviously, the "x" method has to have a way of accessing the instance of the
color made in the "test" method, so the code you've written would handle
that, but your code, itself, doesn't create the instance.

-Scott
 
B

Bob Altman

No problem (no warning) on one computer. Problem (compiler warning) on a
different computer. I'm just trying to figure out what's different between
the two computers.

(I'll leave it to the rest of you to figure out whether or not the first
example should generate a warning. IMO, since the variable does, in fact,
have a shared member that I'm referencing, I would expect the compiler to
give me a warning. I would not expect the compiler to say "well, but I can
ignore the variable reference because it can also be interpreted as a direct
reference to the underlying class".)
 
A

Armin Zingler

Scott M. said:
I disagree with your interpretation of what's going on here. Regardless of
"inside out" processing. Passing a parameter does not
cause an instance of anything to be made as parameters either
receive a copy of data or a copy of a reference to an "already
existing" object. There is no instance being created by this code.

On one side, this is not true, on the other side, it does neither matter
whether an instance is created, nor whether an instance exists at all. The
statement is not true because Color is a value type and the object is passed
ByVal. This means, a copy of the object is created on the stack whenever the
parameter is passed. Thus, passing the object does create a new one.

But as just written, this does not matter. The only thing that is of
interest is to which identifier the name refers. It can either be a
- type name or
- the name of a variable.
Nothing else matters. There is no doubt that the first identifier found by
the compiler is the variable name.


The compile error message could be considered not being completely correct.
Instead of
"Access of shared member through an instance..."
it should be
"Access of shared member through an expression..."

The reason for this is that the variable can be of a reference type and it
points to Nothing. We don't have an instance then, though it can be compiled
and also executed without an error because the compiler is only interested
in the type of the variable in order to access the shared member of that
type. No instance access is done. So, I vote for correcting the error
message. ;-) On the other side, the code looks as if an instance member is
accessed. Maybe that's what the error message wants to tell us.

I wrote "expression", not "variable" because this is also possible:

Sub X()
MsgBox(y.AliceBlue.ToString)
End Sub

Function y() As Color
End Function




If I understood you right, you're saying that the parameter name is ignored
because the compiler is looking for a _type name_ called 'color', right? I
can even proof you that you are wrong:

Public Class Form1

Class Color
Public Shared test As Boolean
End Class
Sub x(ByVal Color As System.Drawing.Color)

Dim o As Color

Color.test = True

End Sub

End Class

First, variable 'o' is of my _own_ type color. That's the proof that name
resolution is done inside out. I think we agree in this point. BUT: If you
were right, the line "Color.test = true" should be compilable! You said that
the paramenter name is ignored. What does the compiler find next? It's my
own class Color. So, why does "Color.Test = true" does not work? It's
because the compiler is only interested in the type of the argument. If it
would ignore the argument name, it MUST be able to compile the code. The
compile error "test is not a member of 'system.drawing.color'" is absolutely
bullet proof.


Armin
 
J

Jack Jackson

But the parameter IS an instance that was passed in.

In these two scenarios:

Private Sub X(color As Color)

and

Dim color As Color

"color" is an instance of the class Color. In neither case is "color"
a reference to the class itself. Therefore color.AliceBlue should
give a warning and Color.AliceBlue should not.

See my other post where for me it appears that using DateTime instead
of Color gives the expected result.

I disagree with your interpretation of what's going on here. Regardless of
"inside out" processing. Passing a parameter does not cause an instance of
anything to be made as parameters either receive a copy of data or a copy of
a reference to an "already existing" object. There is no instance being
created by this code.


Armin Zingler said:
Scott M. said:
No James. No instance variable is being used here.

James is right. See below.
Here's an example that would be accessing a shared member through an
instance variable (pseudo-code) [...]

That's right.
As I said, in the original example, when the compiler sees
"color.AliceBlue", it doesn't assume your are talking about the
"color" parameter, it knows to use the Color class and access its
shared AliceBlue property, which is entirely correct. No instance
of the Color class has been made (either implicitly or explicitly)
and so no error occurs.

The compiler resolves names inside out. In this example

Private Sub X(ByVal color As Color)
Me.BackColor = color.AliceBlue
End Sub

the 2nd line accesses 'color'. When doing name resolution, the compiler
finds the _argument_ named color. This is definitely an instance variable.
Therefore, color.AliceBlue means accessing a shared member through an
instance variable. Therefore the warning.

The compiler does _not_ overlook the argument color, therefore it does
_not_
find the (imported) (System.Drawing.)Color type. You would have to use
System.Drawing.Color, or Drawing.Color as the System namespace is imported
by default, to refer to the _type_ Color.

Though, this does not explain why the OP has different behavior on
different
machines as long as the project's warning settings are the same. Maybe the
"warnings" check box is just not checked in the error/warnings window on
the
other machine.


Armin
 
J

James Hahn

Scott M. said:
No, it is not and that's the source of your confusion. The variable color
isn't an "instance" of the class it is simply a parameter variable that
shadows the Color type's name. The compiler is able to tell the
difference between the two by the context in which the word "color" is
used. Not to mention that parameters don't create instances in the first
place, they are variables that are either passed a data value or a
reference to either a data value or a memory location where an object is
stored. Parameters don't instantiate anything.

Tht's just semantics. Let me rephrase it as "The declaration in the Sub is
advising the compiler that the object that will be passed to the Sub when it
executes will be an instance of the Color class." Did you do as I suggested
and ask the compiler to indicate the definition for the variable?
Your close, but not quite correct here. There is no instance of Color.
That's the whole point of shared type members, you don't call them from an
instance.
You are begging the question. Your comment is reasonable if we assume there
is no instance, but the point of the discussion is whether or not the
compiler believes that the instance exists. The point is that the compiler
reads the original code as attempting to access a shared member of an
instance. It's the compiler, not the programmer, that doesn't (won't) do
this. That's why the compiler is warning the programmer ('you') that it's
not going to do what was coded.
As the OP states, he is NOT getting a warning about this line of code and
the reason he's not is because Color.AliceBlue is understood by the
compiler as accessing a shared member from a "type", not an instance.

No. OP states that he WAS getting a warning on some machines. His concern
was for those cases wher he didn't get a warning.
Again, you are wrong. There is NO instance being created here and the OP
inidcated that he wasn't getting a warning - - only in some cases was a
warning showing up. But, we've already answered the question about the
warning as being related to difference machine's different compiler
warning tolerance settings.

No. Settings have been checked and are not the cause of the problem. The
difference is related somehow to the treatment of an instance with a name
that matches the class name. The OP will always get a warning if the
instance name is different than the class name. The problem was that on
SOME machines the warning is not given if the instance name is the same as
the class name.

If you want to assert that there is no instance then you have to explain why
the compiler issues the warning. I can accept that, in this example, somehow
the compiler is deciding that, since the programmer used an instance name
that matched (almost) the class name, then they were intending that the
reference to the shared variable be through the class, and no warning was
deemed necessary. However, I don't believe the compiler is this subtle (and
further testing indicates this doesn't happen for other classes). But in
any case, the lack of a warning on some machines does not demonstrate that
the compiler is treating the variable as a class instead of an instance.
And the explicit warning on some machines (and on all machines when the name
is different) clearly indicates that the compiler has detected that the
programmer is attempting to do something that the compiler will not do -
namely reference a shared variable through an instance.
 
J

James Hahn

Which suggests that the lack of a warning is related to some oddity in the
compiler's parsing of the label 'color'.
 
A

Armin Zingler

Scott M. said:
No contradiction. This works because this time you are accessing
the R property of the instance of Color that would have to have been
made by the calling procedure, which is perfectly accepatable. What
you've left out is what the calling procedure would look like:

I don't know why you mention the calling procedure at all. It is out of
interest. We can play the same game with local variables only (which in fact
does not make any syntactical difference):

Dim color As Color
Dim b As Byte = color.R 'OK
Dim c As Color = color.AliceBlue 'should give a warning

In the two latter lines, we have exactly the same syntax and we are working
in the same scope. Therefore, you must decide for one of the following:

( ) color. refers to the type name
( ) color. refers to the variable name

No matter what you choose, we must get a warning in one of the two lines. As
I don't get a warning (and Bob on some machines), the compiler does not work
consistently.

I gave another proof in the other message I've just sent.



Armin
 
S

Scott M.

James Hahn said:
You are begging the question. Your comment is reasonable if we assume
there is no instance, but the point of the discussion is whether or not
the compiler believes that the instance exists. The point is that the
compiler reads the original code as attempting to access a shared member
of an instance. It's the compiler, not the programmer, that doesn't
(won't) do this. That's why the compiler is warning the programmer
('you') that it's not going to do what was coded.

No. OP states that he WAS getting a warning on some machines. His concern
was for those cases wher he didn't get a warning.

[Sigh] No James. Read the OP as well as the more recent posts from the OP
and he states that is NOT getting a warning with "color.AliceBlue". That's
becuase the compiler is completely ignoring the "color" parameter and simply
accessing the shared AliceBlue property of the Color type.

The OP said the he has seen warnings on a friend's pc, not his and his most
recent posts confirm what I'm stating here.
No. Settings have been checked and are not the cause of the problem. The
difference is related somehow to the treatment of an instance with a name
that matches the class name. The OP will always get a warning if the
instance name is different than the class name. The problem was that on
SOME machines the warning is not given if the instance name is the same as
the class name.

If you want to assert that there is no instance then you have to explain
why the compiler issues the warning. I can accept that, in this example,
somehow the compiler is deciding that, since the programmer used an
instance name that matched (almost) the class name, then they were
intending that the reference to the shared variable be through the class,
and no warning was deemed necessary. However, I don't believe the
compiler is this subtle (and further testing indicates this doesn't happen
for other classes). But in any case, the lack of a warning on some
machines does not demonstrate that the compiler is treating the variable
as a class instead of an instance. And the explicit warning on some
machines (and on all machines when the name is different) clearly
indicates that the compiler has detected that the programmer is attempting
to do something that the compiler will not do - namely reference a shared
variable through an instance.

I have already explained why the compiler does issue the warning when the
parameter name is different than the class name and the explanation is that
if you want to access AliceBlue from some argument name (say c, rather than
color -- as in c.AliceBlue), then the compiler correctly says to itself "The
only way you could be passing a color type to this procedure is if you had
an instance of it somewhere else and if you have an instance of it somewhere
else, why are you trying to access a shared member of an instance?".

When you coincedentially use the word color as the argument name and then
write color.AliceBlue, the compiler completely ignores the "color" argument
and just assumes you mean "color" as a type and not an instance.

It's very clear what is happening and not really something that is in a grey
area.

-Scott
 
S

Scott M.

Ugh.... It's not an "oddity" it's simply the concept of the parameter
variable name "shadowing" the actual primitive name.
 
S

Scott M.

The only way we can definitively asnwer the why you get it in one place and
not in another is if we could compare each system's setup and configuration,
item for item, but clearly, that is what is causing the disparity, there
must be a difference in either the compiler settings or the compiler
themselves.

-Scott
 
S

Scott M.

Jack Jackson said:
Therefore color.AliceBlue should give a warning and Color.AliceBlue should
not.

VB is not case-sensitive so there is no reason to think that the case you
type it in would have any affect on the compiler.
 
S

Scott M.

Armin Zingler said:
I don't know why you mention the calling procedure at all. It is out of
interest. We can play the same game with local variables only (which in
fact
does not make any syntactical difference):

Dim color As Color
Dim b As Byte = color.R 'OK
Dim c As Color = color.AliceBlue 'should give a warning

None of these line result in a warning for me.
In the two latter lines, we have exactly the same syntax and we are
working
in the same scope. Therefore, you must decide for one of the following:

( ) color. refers to the type name
( ) color. refers to the variable name

No matter what you choose, we must get a warning in one of the two lines.
As
I don't get a warning (and Bob on some machines), the compiler does not
work consistently.

Now, here you are on to something. I think the solution lies in looking at
the IL. But, I don't have time to check that now-- I'll take a look
tomorrow.


-Scott
 
F

Family Tree Mike

I don't think the case has any affect on the compiler. I think that the
compiler is flakey in the ambiguous case where there is an instance variable
name and a class name that are equivalent in a case insensitive way. The
lesson is, only if this ambiguous condition is defined in some VB.Net spec
(and it may be), then programmers just need to live with the poor choice of
coding with such parameter names.
 
B

Branco Medeiros

Scott M. wrote:
[Sigh] No James.  Read the OP as well as the more recent posts from theOP
and he states that is NOT getting a warning with "color.AliceBlue".  That's
becuase the compiler is completely ignoring the "color" parameter and simply
accessing the shared AliceBlue property of the Color type.

The OP said the he has seen warnings on a friend's pc, not his and his most
recent posts confirm what I'm stating here.

Unfortunately it seems you are really mixing things up in at least two
accounts.

First, apparently you think the OP isn't expecting the warning. You
are wrong. The OP knows, as for his posts, that there *should* have
been a warning on his machine. He doesn't understand why there's no
warning and no indication that the compiler is catching up the error
in the code.

I have already explained why the compiler does issue the warning when the
parameter name is different than the class name and the explanation is that
if you want to access AliceBlue from some argument name (say c, rather than
color -- as in c.AliceBlue), then the compiler correctly says to itself "The
only way you could be passing a color type to this procedure is if you had
an instance of it somewhere else and if you have an instance of it somewhere
else, why are you trying to access a shared member of an instance?".

When you coincedentially use the word color as the argument name and then
write color.AliceBlue, the compiler completely ignores the "color" argument
and just assumes you mean "color" as a type and not an instance.

And *that* is you second mix up. The code as is presented is wrong.
There *is* access to a shared member from an instance (yeah, the
choosing of the word "instance" in the warning may be misleading to
you, but I guess it is better than "non type path").

Your explanation of how the compiler is seeing the thing is way far
from the truth, I'm afraid to say. At that exact spot the compiler can
verify that the word "color" refers to a local variable, not to a
type. It doesn't care if the variable is a value type or a reference
type or even if it was correctly initialized (if it was of a reference
type). The compiler, at that moment, is only concerned in verifying if
there is a valid path to member "AliceBlue". Well, there *is* an
AliceBlue member in the Color class but then wait, the member is
marked as shared, so from VB rules a variable reference isn't a valid
path to this member.

Try it in your editor. You won't even be able to list the shared
members in intellisense. The cause of your confusion, it seems to me,
is that your notion of "instance" (correct, btw) is getting in the way
of your understanding. Maybe if the warning was "Access to a shared
member from an element that is not a type" you could actually get it?

Best regards,

Branco.
 
F

Family Tree Mike

Actually, yes, AliceBlue shows in intellisense on my machine for any
instance. It only give's an warning (or is underlined) if it is not "color"
in spelling.



Try it in your editor. You won't even be able to list the shared
members in intellisense. The cause of your confusion, it seems to me,
is that your notion of "instance" (correct, btw) is getting in the way
of your understanding. Maybe if the warning was "Access to a shared
member from an element that is not a type" you could actually get it?

Best regards,

Branco.
 
B

Bob Altman

And the big question is still, what is different on these various
machines?


I'll be at PDC (the Microsoft Professional Developer's Conference) this
week. I'm going to see if I can get any insight from any of the MS
developers hanging out in the lounge.

Bob
 
S

Scott M.

Unfortunately it seems you are really mixing things up in at least two
accounts.
First, apparently you think the OP isn't expecting the warning. You are
wrong.

No, I'm acutally trying to tell the OP that he shouldn't be expecting a
warning. And, since no warning is given, I'm explaining why.
The OP knows, as for his posts, that there *should* have
been a warning on his machine.

Yes, and the OP is wrong to expect a warning.
He doesn't understand why there's no
warning and no indication that the compiler is catching up the error
in the code.

Again, yes - but just because he "expects" a warning doesn't mean he
"should" get one. I have been explaining that the reason he's not getting
one (which is the correct behavior) is because he is NOT accessing a shared
member through an inistance.
When you coincedentially use the word color as the argument name and then
write color.AliceBlue, the compiler completely ignores the "color"
argument
and just assumes you mean "color" as a type and not an instance.
And *that* is you second mix up. The code as is presented is wrong.
There *is* access to a shared member from an instance (yeah, the
choosing of the word "instance" in the warning may be misleading to
you, but I guess it is better than "non type path").

As you correctly say (as I did as well)

<snip>
The compiler, at that moment, is only concerned in verifying if
there is a valid path to member "AliceBlue".
</snip>

This does follow exactly with what I stated. The compiler is trying to find
AliceBlue and it does, through the shared member of the Color type. Since
the reference to AliceBlue is through the type named "color", it assumes
that "color" refers to the type, not the variable.

<snip>
....so from VB rules a variable reference isn't a valid path to this member.
</snip>

Perhaps, but it's a good thing the compiler doesn't attempt to resolve
"color" as a variable, but instead resolves it to mean the type "color" and
hence, no warning.
Try it in your editor. You won't even be able to list the shared
members in intellisense.

I think you should try it in your editor, because in mine, I do get the
shared members lisf after typing "color."
The cause of your confusion, it seems to me,
is that your notion of "instance" (correct, btw) is getting in the way
of your understanding. Maybe if the warning was "Access to a shared
member from an element that is not a type" you could actually get it?

I don't think your description has anything to do with anything. My
understanding of what "instance" means isn't getting in the way of anything.
I think you've misunderstood what you've read.

-Scott
 
J

James Hahn

You assert that this behaviour is 'correct' without any supporting argument
(other than that it seems sensible to you).

Perhaps you would like to refer us all to your MS reference for this single
exception to the standard name resolution rules in VB. Or some other case
where VB similarly ignores the standard rules without any warning.
 

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