Guid readonly?

  • Thread starter Thread starter Pohihihi
  • Start date Start date
P

Pohihihi

I guess I am forgetting some rules, why I am not able to do following, says it is read only --


Guid[] a = new Guid[2];
foreach(Guid b in a)
b = Guid.Empty;

but can do as following --

int c = 0;
while(c < a.Length)
a[c++] = Guid.Empty;
 
This has to do with the restrictions applicable to your variable ("b")
in the foreach statment: System.Guid is a value-type (a struct),
therefore, it is read-only. Cf. "foreach, in" in MSDN (C# Programmer's
Reference).
 
Collection (and possibly arrays) cannot be changed when using the foreach
construct.

When foreach is used, it locks the objects to ensure that the information
returned from the enumerator is consistent and does not change. Although
your scenario probably will not cause the enumerator to get confused, it
locks it so that you cannot add or remove elements in something like an
array list.

I guess I am forgetting some rules, why I am not able to do following, says
it is read only --


Guid[] a = new Guid[2];
foreach(Guid b in a)
b = Guid.Empty;

but can do as following --

int c = 0;
while(c < a.Length)
a[c++] = Guid.Empty;
 
It did not come in my mind to check foreach docs for this. Yes, that is that
case, I read it just now.
Thx.
 
Actually, the value type is not read only. What happens in this
situation is that in the foreach statement, b is a copy of the Guid from a.
This is due to the assignment semantics on value types, where it is copied
on assignment. The reason why you can make the assignment in the for loop
is because the loop is accessing the array directly.

Hope this helps.
 
Nicholas Paldino said:
Actually, the value type is not read only.

I'm not sure what you mean by this, but the variable itself is
certainly read only - and if you were able to directly set any fields
within the struct normally, they would be read only too. Here's an
example:

using System;

struct Foo
{
public int x;
}

class Test
{
static void Main()
{
Foo[] f = new Foo[10];
foreach (Foo foo in f)
{
foo.x = 10;
foo = new Foo();
}
}
}

Both of the assignments fail - foo.x isn't classified as a variable
because foo is readonly, and the direct assignment fails for the same
reason.

From the spec:

<quote>
In either expansion, the enumerator variable is a temporary variable
that is inaccessible in, and invisible to, the embedded statement, and
the element variable is read-only in the embedded statement.
</quote>

Note the last phrase.

Your post gave the reason why if it *did* compile, it still wouldn't do
what Pohihihi wanted - but the above is why it didn't compile in the
first place.
 
Peter Rilling said:
Collection (and possibly arrays) cannot be changed when using the foreach
construct.

When foreach is used, it locks the objects to ensure that the information
returned from the enumerator is consistent and does not change. Although
your scenario probably will not cause the enumerator to get confused, it
locks it so that you cannot add or remove elements in something like an
array list.

I don't think that's quite the reason. I believe the reason is that if
the foreach variable weren't read-only, people might assume that if
they changed the value, the value within the collection would change -
which it wouldn't.
 
Pohihihi stated:

System.Guid is a value-type (a struct), therefore, it is read-only

Implying that value types are read only by default. I should have said
"value types" and not "a value type". It was a comment about the other
comment about the inherent nature of value types, not whether or not it was
read-only due to the nature of it being a value type.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Jon Skeet said:
Nicholas Paldino said:
Actually, the value type is not read only.

I'm not sure what you mean by this, but the variable itself is
certainly read only - and if you were able to directly set any fields
within the struct normally, they would be read only too. Here's an
example:

using System;

struct Foo
{
public int x;
}

class Test
{
static void Main()
{
Foo[] f = new Foo[10];
foreach (Foo foo in f)
{
foo.x = 10;
foo = new Foo();
}
}
}

Both of the assignments fail - foo.x isn't classified as a variable
because foo is readonly, and the direct assignment fails for the same
reason.

From the spec:

<quote>
In either expansion, the enumerator variable is a temporary variable
that is inaccessible in, and invisible to, the embedded statement, and
the element variable is read-only in the embedded statement.
</quote>

Note the last phrase.

Your post gave the reason why if it *did* compile, it still wouldn't do
what Pohihihi wanted - but the above is why it didn't compile in the
first place.
 
I'm sorry, but this seems to me a deliberate misread of my post. When
did I say that value types are read-only by default? When did I comment
on "the inherent nature of value types?" Value-types are read-only in
the context I was referring to them in, that is all.
 
Back
Top