Yes, it could. The compiler knows, at least to some degree, that a
method changes the struct that owns it.
I'm not sure why you say that. As it's compiling the method, it's true
that information is present. But outside of that case, how would the
compiler know the method changes the struct? Should it flag all methods
that change a struct somehow, and cache that information somewhere for use
when compiling other code? Should the linker be required to carry this
flag around too, so that when you import a reference to a struct type not
compiled with the current project, you still have that information?
This is a similar issue to
C#'s lack of 'const' for variables and methods. If it had the
internal features that checked such things, then it'd know.
I don't see it as "similar". I see it as identical.
If C# had "const" for variables and methods, then it would also have the
function name decoration that's used to convey that information that
C++ has. Then when compiling code that uses a method, *if* the "const"
keyword were used, it could know that the method doesn't change the struct.
But then what is the compiler supposed to do with methods not marked as
"const"? Should it automatically assume that the method *does* change the
struct? And in that case, should the compiler instead of copying the
value type create some sort of hidden reference to it on which the method
can operate? And if so, why shouldn't the compiler just always do that?
[...]
(Remember when we warned you about making mutable structs, back in
March? This is just one of the problems. Just say no to mutable
structs, basically
Yup!
But, it just doesn't seem fair, since the language isn't
quite 'complete', yet.
IMHO, C# is only "not quite complete" in the same way that C++ and BASIC
and FORTRAN are all "not quite complete".
More specifically, it seems to me that C# has pretty well decided what
value types are going to do and not do, and it's pretty clear that you
don't get to have references to value types. Given the lack of references
I never had troubles with Lists in C++ like
this.
You would have if there were any implementations of lists in C++ that
provided access to list items by value. There may in fact be such an
implementation, and if there is, it will have the same issue. It will
return a copy of a value within the list, and you can operate on that copy
'till the cows come home and the item in the list will never change.
But, it's becoming obvious that the c# designers just want us
to use reference types when we can, and everything in the langauge is
based on this, and thus, it is wildly different than C++ in that
regard. I guess there's good and bad that comes with that.
I wouldn't agree that the designers want you to use reference types when
you can. There's a time and place for a value type, and in fact they even
have their place in lists. But it seems to me that other than some
semantic oddities (that I've complained about myself
), the basic
behavior is well-defined.
I agree that this particular example is somewhat confusing. In the same
way that overloading the "new" operator bugs me about reference types
versus value types, you're dealing with a situation in which the indexing
operator "[]" behaves differently depending on whether you've got an array
or a List<>. With an array, you get the actual item in the array. With a
List<> you get the value from the array, which is always a copy of the
item in the array (and if it's a copy of the reference then you can still
directly act upon the instance referenced). But once you understand this
difference, the underyling "reference vs value" behavior is consistent and
reliable.
Pete