By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,830 Members | 1,746 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,830 IT Pros & Developers. It's quick & easy.

List<> of struct with property. Cannot change value of property. why?

P: n/a
This returns the following error:
"Cannot modify the return value of
'System.Collections.Generic.List<MyStruct>.this[int]' because it is
not a variable"
and I have no idea why! Do lists return copies of their elements?
Why can't I change the element itself?

class Program
{
private struct MyStruct
{
private int myVar;
public int MyProperty
{
get { return myVar; }
set { myVar = value; }
}
}

private static List<MyStructlist = new List<MyStruct>();

private static void Main(string[] args)
{
MyStruct x = new MyStruct();
x.MyProperty = 45;
list.Add(x);
list[0].MyProperty = 45; // <----------- ERROR HERE
}
}

Zytan

May 14 '07 #1
Share this Question
Share on Google+
45 Replies


P: n/a
On May 14, 10:28 am, Zytan <zytanlith...@gmail.comwrote:
This returns the following error:
"Cannot modify the return value of
'System.Collections.Generic.List<MyStruct>.this[int]' because it is
not a variable"
and I have no idea why! Do lists return copies of their elements?
Yes. The [] operator on a list is, in fact, a function, so the value
stored at that location in the list is returned as a function result,
on the stack.

This doesn't cause problems for reference types, because usually you
want to change some property of the reference type, so the fact that
you get a copy of the reference in the list (not the actual reference
that is in the list) doesn't cause problems.

However, for value types exactly the same thing happens, and it does
cause problems: the value is copied from the list onto the stack and
returned as a function result. Modifying the returned value, of
course, has no effect on the contents of the list. The compiler wisely
catches this.
Why can't I change the element itself?

class Program
{
private struct MyStruct
{
private int myVar;
public int MyProperty
{
get { return myVar; }
set { myVar = value; }
}
}

private static List<MyStructlist = new List<MyStruct>();

private static void Main(string[] args)
{
MyStruct x = new MyStruct();
x.MyProperty = 45;
list.Add(x);
list[0].MyProperty = 45; // <----------- ERROR HERE
}
}
You need to do this:

MyStruct y = list[0];
y.MyProperty = 45;
list[0] = y;

May 14 '07 #2

P: n/a
Yes. The [] operator on a list is, in fact, a function, so the value
stored at that location in the list is returned as a function result,
on the stack.
Ok.
This doesn't cause problems for reference types, because usually you
want to change some property of the reference type, so the fact that
you get a copy of the reference in the list (not the actual reference
that is in the list) doesn't cause problems.
Right, so that's why it's normally not an issue.
However, for value types exactly the same thing happens, and it does
cause problems: the value is copied from the list onto the stack and
returned as a function result. Modifying the returned value, of
course, has no effect on the contents of the list. The compiler wisely
catches this.
Yup, and structs are value types, so this makes sense.
You need to do this:

MyStruct y = list[0];
y.MyProperty = 45;
list[0] = y;
Ok, thanks, Bruce!! This helps a lot!

Zytan

May 14 '07 #3

P: n/a
The compiler wisely
catches this.
NOTE, the compiler does NOT catch everything! The following code
escapes detection:

MyStruct x = new MyStruct();
list[index].MethodThatChangesStructsFields(x);

I guess this could be shortened to:

list[index].MethodThatChangesStructsFields();

And likely THAT escapes detection, as well. Damn! I've been changing
all my ararys that are created dynamically (length unknown) into
List<>, to avoid Array.Resize.

Zytan

May 14 '07 #4

P: n/a
I guess this could be shortened to:
>
list[index].MethodThatChangesStructsFields();
Confirmed. This operates on the COPY, and any changes are lost, and
the compiler does NOT warn about this.

Zytan

May 14 '07 #5

P: n/a
On Mon, 14 May 2007 11:38:10 -0700, Zytan <zy**********@gmail.comwrote:
[...]
I guess this could be shortened to:

list[index].MethodThatChangesStructsFields();

And likely THAT escapes detection, as well. Damn! I've been changing
all my ararys that are created dynamically (length unknown) into
List<>, to avoid Array.Resize.
Well, you can still apply the same technique Bruce mentions:

MyStruct x = list[index];

x.MethodThatChangesStructsFields();
list[index] = x;

Pete
May 14 '07 #6

P: n/a
Zytan <zy**********@gmail.comwrote:
I guess this could be shortened to:

list[index].MethodThatChangesStructsFields();

Confirmed. This operates on the COPY, and any changes are lost, and
the compiler does NOT warn about this.
No, and there's no way it could. There's nothing available to the
compiler to let it know that the method changes the contents of the
struct.

(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 :)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
May 14 '07 #7

P: n/a

If you declare your structure to implement an interface and then
declare the list as containing the interface instead of the structure,
then you can work with the structure (through the interface
implemented members) directly (interfaces allow you to pierce the
box).

Code sample below.
HTH,

Sam
------------------------------------------------------------
We're hiring! B-Line Medical is seeking .NET
Developers for exciting positions in medical product
development in MD/DC. Work with a variety of technologies
in a relaxed team environment. See ads on Dice.com.
public static void Test()
{
MyClass[] classArray = new MyClass[1];
MyStruct[] structArray = new MyStruct[1];
MyInterface[] interfaceArray = new MyInterface[1];
List<MyClassclassList = new List<MyClass>(1);
List<MyStructstructList = new List<MyStruct>(1);
List<MyInterfaceinterfaceList = new List<MyInterface>(1);

classArray[0] = new MyClass();
classList.Add(new MyClass());
interfaceArray[0] = new MyStruct();
structList.Add(new MyStruct());
interfaceList.Add(new MyStruct());

classArray[0].X++;
interfaceArray[0].X++;
structArray[0].X++;
classList[0].X++;

// Cannot modify the return value of 'List<MyStruct>.this[int]'
// because it is not a variable
//structList[0].X++;
interfaceList[0].X++;

Console.WriteLine("Class Array : " + classArray[0].X);
Console.WriteLine("Struct Array : " + structArray[0].X);
Console.WriteLine("Interface Array : " + interfaceArray[0].X);
Console.WriteLine("Class List : " + classList[0].X);
Console.WriteLine("Struct List : " + structList[0].X);
Console.WriteLine("Interface List : " + interfaceList[0].X);
}
}

public class MyClass : MyInterface
{
private int x;

public int X
{
get
{
return x;
}
set
{
x = value;
}
}
}

public struct MyStruct : MyInterface
{
private int x;

public int X
{
get
{
return x;
}
set
{
x = value;
}
}
}

public interface MyInterface
{
int X { get; set; }
}
On 14 May 2007 10:28:01 -0700, Zytan <zy**********@gmail.comwrote:
>This returns the following error:
"Cannot modify the return value of
'System.Collections.Generic.List<MyStruct>.this[int]' because it is
not a variable"
and I have no idea why! Do lists return copies of their elements?
Why can't I change the element itself?

class Program
{
private struct MyStruct
{
private int myVar;
public int MyProperty
{
get { return myVar; }
set { myVar = value; }
}
}

private static List<MyStructlist = new List<MyStruct>();

private static void Main(string[] args)
{
MyStruct x = new MyStruct();
x.MyProperty = 45;
list.Add(x);
list[0].MyProperty = 45; // <----------- ERROR HERE
}
}

Zytan
May 14 '07 #8

P: n/a
On May 14, 12:25 pm, Samuel R. Neff <samueln...@nomail.comwrote:
If you declare your structure to implement an interface and then
declare the list as containing the interface instead of the structure,
then you can work with the structure (through the interface
implemented members) directly (interfaces allow you to pierce the
box).

Code sample below.

HTH,

Sam

------------------------------------------------------------
We're hiring! B-Line Medical is seeking .NET
Developers for exciting positions in medical product
development in MD/DC. Work with a variety of technologies
in a relaxed team environment. See ads on Dice.com.

public static void Test()
{
MyClass[] classArray = new MyClass[1];
MyStruct[] structArray = new MyStruct[1];
MyInterface[] interfaceArray = new MyInterface[1];
List<MyClassclassList = new List<MyClass>(1);
List<MyStructstructList = new List<MyStruct>(1);
List<MyInterfaceinterfaceList = new List<MyInterface>(1);

classArray[0] = new MyClass();
classList.Add(new MyClass());
interfaceArray[0] = new MyStruct();
structList.Add(new MyStruct());
interfaceList.Add(new MyStruct());

classArray[0].X++;
interfaceArray[0].X++;
structArray[0].X++;
classList[0].X++;

// Cannot modify the return value of 'List<MyStruct>.this[int]'
// because it is not a variable
//structList[0].X++;
interfaceList[0].X++;

Console.WriteLine("Class Array : " + classArray[0].X);
Console.WriteLine("Struct Array : " + structArray[0].X);
Console.WriteLine("Interface Array : " + interfaceArray[0].X);
Console.WriteLine("Class List : " + classList[0].X);
Console.WriteLine("Struct List : " + structList[0].X);
Console.WriteLine("Interface List : " + interfaceList[0].X);
}

}

public class MyClass : MyInterface
{
private int x;

public int X
{
get
{
return x;
}
set
{
x = value;
}
}

}

public struct MyStruct : MyInterface
{
private int x;

public int X
{
get
{
return x;
}
set
{
x = value;
}
}

}

public interface MyInterface
{
int X { get; set; }

}
Now I'm curious: does the array MyInterface[] contain the actual
values, or does one incur boxing overhead when putting the value into
the array? In other words, is it an array of MyStruct, or an array of
boxes of MyStructs?

May 14 '07 #9

P: n/a
Bruce Wood <br*******@canada.comwrote:
Now I'm curious: does the array MyInterface[] contain the actual
values, or does one incur boxing overhead when putting the value into
the array? In other words, is it an array of MyStruct, or an array of
boxes of MyStructs?
Boxes - the values are references, and have to be, given that you could
use a reference type implementation.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
May 14 '07 #10

P: n/a

They are boxes, but it's not 100% the same as boxing in other
situations. Because of the interface they are boxed once and can
therefore be manipulated within the box, so you can do things to them
without unboxing. So you get boxing overhead possibly without
unboxing overhead.

For code clarity and consistency I would lean towards using immutable
structures, but it's an interesting technical clarification. :-)

Sam

------------------------------------------------------------
We're hiring! B-Line Medical is seeking .NET
Developers for exciting positions in medical product
development in MD/DC. Work with a variety of technologies
in a relaxed team environment. See ads on Dice.com.

On 14 May 2007 13:31:30 -0700, Bruce Wood <br*******@canada.com>
wrote:
>On May 14, 12:25 pm, Samuel R. Neff <samueln...@nomail.comwrote:
>If you declare your structure to implement an interface and then
declare the list as containing the interface instead of the structure,
then you can work with the structure (through the interface
implemented members) directly (interfaces allow you to pierce the
box).

Code sample below.

HTH,

Sam
....
>
Now I'm curious: does the array MyInterface[] contain the actual
values, or does one incur boxing overhead when putting the value into
the array? In other words, is it an array of MyStruct, or an array of
boxes of MyStructs?
May 14 '07 #11

P: n/a
Samuel R. Neff <sa********@nomail.comwrote:
They are boxes, but it's not 100% the same as boxing in other
situations. Because of the interface they are boxed once and can
therefore be manipulated within the box, so you can do things to them
without unboxing. So you get boxing overhead possibly without
unboxing overhead.
It's worth clarifying here that the boxing itself is exactly the same
as normal. Indeed, you can take something that has been boxed in a
different way and cast it to the interface:

object o = 5; // Normal boxing
IComparable c = (IComparable)o; // Normal reference cast
For code clarity and consistency I would lean towards using immutable
structures, but it's an interesting technical clarification. :-)
Agreed :)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
May 14 '07 #12

P: n/a
No, and there's no way it could. There's nothing available to the
compiler to let it know that the method changes the contents of the
struct.
Yes, it could. The compiler knows, at least to some degree, that a
method changes the struct that owns it. 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. Then, it
could warn that you are changing a struct from a method marked as
'const' (which guarantees to do no such thing), and it could fire a
warning for the above case of modifying a temporary.
(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. I never had troubles with Lists in C++ like
this. 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.

Zytan

May 14 '07 #13

P: n/a
On Mon, 14 May 2007 14:44:50 -0700, Zytan <zy**********@gmail.comwrote:
>No, and there's no way it could. There's nothing available to the
compiler to let it know that the method changes the contents of the
struct.

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
to value types, I don't see any clean way to have a List<return a
reference to a value type within the list for some method to operate on.
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
May 14 '07 #14

P: n/a
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?
The same way C++ deals with const methods.
Should it flag all methods
that change a struct somehow, and cache that information somewhere for use
when compiling other code?
Yes, but it would seem less silly if there were more reasons to use
such information. And having "const" is a large one.
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?
I have no idea, but I would assume that a C++ linker does. After all,
it's just one bit.
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.
Yup.
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?
In c++, if you have a method that doesn't change it, but you don't
tell it specifically that it doesn't change it, then the compiler
assumes that it COULD change it, and thus doesn't trust that it's
being nice. So, it's not that it assumes it does change it, it just
assumes that it could change it. And if that's an issue, which it is
for a method called on a temporary copy (are these called
'temporaries'?), then the compiler could say, hey, since you didn't
say you won't modify this struct, it means you may modify it, and if
you do, you're not going to get what you expect. Just a friendly
warning.
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?
No, it shouldn't do your work for you. It's just there to notify you
when you're being stupid.
IMHO, C# is only "not quite complete" in the same way that C++ and BASIC
and FORTRAN are all "not quite complete".
I agree.
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
to value types, I don't see any clean way to have a List<return a
reference to a value type within the list for some method to operate on.
I am still programming in C++ mode. It's taking me a while to realize
that structs become more useless when the language is built mainly
around reference types.
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.
I was referring to the STL, which is part of the (or at least the
defacto) standard. It was put together surprisingly well.
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 guess at the moment I decided to have a method in my struct, I
should have moved to a class.
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.
Yup. thanks for your comments, Pete

Zytan

May 14 '07 #15

P: n/a
Zytan <zy**********@gmail.comwrote:
No, and there's no way it could. There's nothing available to the
compiler to let it know that the method changes the contents of the
struct.

Yes, it could. The compiler knows, at least to some degree, that a
method changes the struct that owns it.
Well, the compiler certainly doesn't know it from the metadata about
the method. Are you suggesting that the compiler should start looking
at the *implementation* of the method (which could be in a different
assembly) to work out what to do? What if the implementation changes?
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.
And then that would show up in the method metadata, yes - but as it is,
that information isn't there.
Then, it could warn that you are changing a struct from a method
marked as 'const' (which guarantees to do no such thing), and it
could fire a warning for the above case of modifying a temporary.
Again, if "const" were available, that would make a lot of sense - but
it isn't, for better or worse.
(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. I never had troubles with Lists in C++ like
this. 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.
It's wildly different from C++ in many ways. I think those who haven't
used C++ to start with actually have an advantage when learning C#, in
terms of not having to "unlearn" things.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
May 14 '07 #16

P: n/a
Zytan <zy**********@gmail.comwrote:

<snip>
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 guess at the moment I decided to have a method in my struct, I
should have moved to a class.
No - there are plenty of times it makes sense to have methods in
structs. Look at DateTime - loads of methods in there, and it's still a
perfectly good value type. It just doesn't have any methods which
mutate it.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
May 14 '07 #17

P: n/a
No - there are plenty of times it makes sense to have methods in
structs. Look at DateTime - loads of methods in there, and it's still a
perfectly good value type. It just doesn't have any methods which
mutate it.
Right. So. Structs should be immutable. That's the golden rule?
All fields should be private (or readonly) with the constructor
setting them?

Zytan

May 14 '07 #18

P: n/a
Peter Duniho <Np*********@nnowslpianmk.comwrote:

<snip>
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.
Or to be specific (and odd!) you get the *variable* in the array.
That's the weird bit - that an array isn't a collection of values, it's
a collection of variables (in the spec, anyway). So

int[] n = new int[4];
is sort of equivalent to:

int n0 = 0;
int n1 = 0;
int n2 = 0;
int n3 = 0;

(except sized at runtime, of course).

That's why you can pass array elements by reference, too. Conceptually
slightly odd, IMO.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
May 14 '07 #19

P: n/a
Zytan <zy**********@gmail.comwrote:
No - there are plenty of times it makes sense to have methods in
structs. Look at DateTime - loads of methods in there, and it's still a
perfectly good value type. It just doesn't have any methods which
mutate it.

Right. So. Structs should be immutable. That's the golden rule?
It's at least a silver rule. There may be good reasons to have
genuinely mutable structs in very special cases, but I haven't seen
them yet.
All fields should be private (or readonly) with the constructor
setting them?
Fields should be private anyway, but yes, they should be private and
probably all readonly, unless you want to set them from private methods
called in the constructor.

Of course, you might want to have mutable fields for caching purposes
(e.g. caching the result of calling GetHashcode) which don't change the
perceivable state - no harm in that, although it would be unusual.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
May 14 '07 #20

P: n/a
"Jon Skeet [C# MVP]" <sk***@pobox.comschrieb im Newsbeitrag
news:MP********************@msnews.microsoft.com.. .
>The compiler knows, at least to some degree, that a
method changes the struct that owns it.

Well, the compiler certainly doesn't know it from the metadata about
the method. Are you suggesting that the compiler should start looking
at the *implementation* of the method (which could be in a different
assembly) to work out what to do? What if the implementation changes?
If C# had const methods similar to C++, then this could be stored in the
metadata. And the compiler could check this while compiling the method. But
that certainly would be problematic if different languages are used. Other
languages should use the same attribute, and methods from languages, that
don't use that same attribute would be regarded as possibly changing the
struct. This problem I suppose, doesn't exsist in C++, does it?

BTW How does C++ handle const methods from other modules?

Christof
May 15 '07 #21

P: n/a
"Samuel R. Neff" <sa********@nomail.comschrieb im Newsbeitrag
news:eo********************************@4ax.com...
>
They are boxes, but it's not 100% the same as boxing in other
situations. Because of the interface they are boxed once and can
therefore be manipulated within the box, so you can do things to them
without unboxing. So you get boxing overhead possibly without
unboxing overhead.

For code clarity and consistency I would lean towards using immutable
structures, but it's an interesting technical clarification. :-)
Yes, but unboxing had much less overhead. IIUC it's only one additional
indirection while fetching the value.
No object creation there.

Christof
May 15 '07 #22

P: n/a
Well, the compiler certainly doesn't know it from the metadata about
the method. Are you suggesting that the compiler should start looking
at the *implementation* of the method (which could be in a different
assembly) to work out what to do? What if the implementation changes?
No, I am not suggesting that.

I am suggesting that it could do it in the same way C++ does it. C++
solved it, so it's solvable. Likely, it's stored in the "metadata"
whatever that means, presumably in the information that it arrives at
when compiling the method, so that someone else who uses it doesn't
have to look at the implementation, just the analysis.
And then that would show up in the method metadata, yes - but as it is,
that information isn't there.
I know it lacks this information. But, it could do it, there's no
doubt.
Again, if "const" were available, that would make a lot of sense - but
it isn't, for better or worse.
Yup.
It's wildly different from C++ in many ways. I think those who haven't
used C++ to start with actually have an advantage when learning C#, in
terms of not having to "unlearn" things.
I think I like that C++ is a little closer to reality, that is, how
the computer does things. C# is a little bit removed. Each has its
advantages. To some degree, a good program / programmer needs both.
So, you shouldn't have to "unlearn" anything, but you do only because
it hides the truth. Of course, C++ does it's fair share of hiding
things, too, so an identical argument could be made on C++ vs
assembly.

Zytan

May 15 '07 #23

P: n/a
On Tue, 15 May 2007 03:52:06 -0700, Christof Nordiek <cn@nospam.dewrote:
[...]
BTW How does C++ handle const methods from other modules?
As far as I can recall, C++ does not use the "const" information in the
way that Zytan is asking for C# to. That is, the "const" attribute of a
method or parameters doesn't affect how an item is retrieved from a data
structure or how a function is called. It only controls whether the
compiler can assume, for the purpose of evaluating "const"-ness in the
code being compiled, that the called function doesn't modify the data.

That is, the main reason it's useful in external modules is so that your
own modules can use "const" too. :)

If C# *did* have the "const" keyword, I would expect it to work more like
that, than in the way that Zytan would like it to work.

Pete
May 15 '07 #24

P: n/a
On Tue, 15 May 2007 07:13:03 -0700, Zytan <zy**********@gmail.comwrote:
[...]
I am suggesting that it could do it in the same way C++ does it. C++
solved it, so it's solvable.
Well, note that C++ implements it by including the "const" right in the
function name. Also note that C++ doesn't use "const" in the way that
you'd like C# to use it (see my previous post). I'm not sure it's fair to
say that "C++ solved it", since C++ doesn't really solve the problem we
started out talking about.

Frankly, I think C# already has enough implicit code-generation gotchas as
it is. Things like overloading hiding certain type conversions, for
example. I doubt that even if C# had a "const" operator, I'd want it
accessing elements in a List<differently depending on whether I was
calling a method immediately on the item, and whether that method was
labeled "const".

Pete
May 15 '07 #25

P: n/a
As far as I can recall, C++ does not use the "const" information in the
way that Zytan is asking for C# to. That is, the "const" attribute of a
method or parameters doesn't affect how an item is retrieved from a data
structure or how a function is called. It only controls whether the
compiler can assume, for the purpose of evaluating "const"-ness in the
code being compiled, that the called function doesn't modify the data.

That is, the main reason it's useful in external modules is so that your
own modules can use "const" too. :)

If C# *did* have the "const" keyword, I would expect it to work more like
that, than in the way that Zytan would like it to work.
I think I am saying the same thing.

Once you have this boolean value that states the "const"-ness of a
method, then in the case of calling a non-const method on a List<>
element that is a temporary (the compiler already knows when it's a
temporary), the compiler could complain and say: "Hey, you might be
modifying a temporary! You should only call const-methods on
temporaries!"

Zytan

May 15 '07 #26

P: n/a
Well, note that C++ implements it by including the "const" right in the
function name. Also note that C++ doesn't use "const" in the way that
you'd like C# to use it (see my previous post). I'm not sure it's fair to
say that "C++ solved it", since C++ doesn't really solve the problem we
started out talking about.
I think we are speaking about the same thing, so perhaps you
misunderstand my idea. I just thought if C# had "const" like C++
does, then it could go one step further, and make use of it to show a
warning that you are calling a non-const (i.e. potentially modifying)
method on a temporary, which seems pointless.
Frankly, I think C# already has enough implicit code-generation gotchas as
it is. Things like overloading hiding certain type conversions, for
example. I doubt that even if C# had a "const" operator, I'd want it
accessing elements in a List<differently depending on whether I was
calling a method immediately on the item, and whether that method was
labeled "const".
No, I wouldn't want things to change depending if it had const-ness or
not! It could just be used for a helpful warning, that's all: Why
call a method that changes the class when the class is a temporary,
and is thrown away before you can even see or use it?

Zytan

May 15 '07 #27

P: n/a
On Tue, 15 May 2007 14:20:51 -0700, Zytan <zy**********@gmail.comwrote:
>If C# *did* have the "const" keyword, I would expect it to work more
like that, than in the way that Zytan would like it to work.

I think I am saying the same thing.
Sorry...I guess I misunderstood what you wanted the language to do.
Once you have this boolean value that states the "const"-ness of a
method, then in the case of calling a non-const method on a List<>
element that is a temporary (the compiler already knows when it's a
temporary), the compiler could complain and say: "Hey, you might be
modifying a temporary! You should only call const-methods on
temporaries!"
Well, IMHO the compiler could easily provide the same warning today,
without the "const" keyword.

After all, in C++ there's a LOT of code that doesn't modify data that
isn't marked "const". Relying on the "const" keyword to enable a warning
wouldn't have been a good idea in C++, because you'd get a lot of false
positives due to the large amount of code that is "const" without using
"const".

Conversely, if such a warning is a good idea (in C# or C++), it seems to
me that the compiler ought to just warn and forget about trying to
determine whether the method is actually a "const" method or not.

Personall, because of the false positive issue, I think such a warning
isn't a good idea. You'd see it far too often when it wasn't legitimate
for it to actually be useful.

Now, I suppose the language could add a feature in which it requires the
compiler to analyze every method and apply its own "const" attribute based
on that analysis. But that opens a whole new can of worms, including what
is essentially the same problem that the C++ "const" keyword had: until
every single function in the call chain supports that attribute, you wind
up with a lot of functions that can't be marked as "const" even though
they really are (or conversely, you have to do casting a bunch of stuff to
glue the const/not-const stuff together).

My feeling is that while it's possible theoretically to address the issue,
I think it's simpler to just make the language simple and consistent, and
require developers to understand that the List<"[]" operator is
providing a copy of the element in the list. There's too many situations
where working directly with the copied value is useful for the compiler to
go around warning you every time you do it, and introducing a "const"
attribute (explicit or implicit) creates far too many new hassles to make
it worth the trouble.

Opinions will vary, of course. :)

Pete
May 15 '07 #28

P: n/a
On Tue, 15 May 2007 14:25:19 -0700, Zytan <zy**********@gmail.comwrote:
I think we are speaking about the same thing, so perhaps you
misunderstand my idea. I just thought if C# had "const" like C++
does, then it could go one step further, and make use of it to show a
warning that you are calling a non-const (i.e. potentially modifying)
method on a temporary, which seems pointless.
I think I cover this adequately in the article I just posted, but just for
completeness...

The problem (well, "a problem" anyway) is that lots of methods are
essentially "const" even though no one's bothered to mark them as such.
For that matter, lots of methods are essentially "const" even though they
can't be marked as such, because they might call some other code that is
essentially "const" but which isn't marked as such.

I suppose you could work it the other way around, claiming that code is
"const" unless otherwise marked (say, introduce an "unconst" keyword you
have to use any time you want a method to be able to change things). But
then you'd have the language assuming a bunch of external functions are
const even though they are not (or if the language doesn't do that, you
wind up with the previous problem *plus* an inconsistency in how functions
are treated).
No, I wouldn't want things to change depending if it had const-ness or
not! It could just be used for a helpful warning, that's all: Why
call a method that changes the class when the class is a temporary,
and is thrown away before you can even see or use it?
Well, a *class* _isn't_ temporary. If you get a reference from a List<>,
then yes you get a copy of the reference, just like you get a copy of a
value type. But the reference refers to a single instance, and if you
change that instance, that change is reflected whether you look at the
copied reference you're using, or the original reference stored in the
List<>.

Pete
May 15 '07 #29

P: n/a
After all, in C++ there's a LOT of code that doesn't modify data that
isn't marked "const". Relying on the "const" keyword to enable a warning
wouldn't have been a good idea in C++, because you'd get a lot of false
positives due to the large amount of code that is "const" without using
"const".
Actually, in a good programmer's hands, that's a notice to the compiler that
the function is not guaranteed to leave the data unchanged. I'd hate for
the compiler to analyze a stub function, make an automatic determination of
const-ness, and somehow affect how the code around it is error-checked.
(Note that optimizing the generated machine code is ok, optimizing away
errors and warnings is not).

Understanding and using const-correctness is a prerequisite for being a
professional C++ programmer. It's an important part of documentation,
compile-time error checking, and enables automatic optimizations that
couldn't otherwise be performed.
May 15 '07 #30

P: n/a
On Tue, 15 May 2007 15:07:56 -0700, Ben Voigt <rb*@nospam.nospamwrote:
[...]
Understanding and using const-correctness is a prerequisite for being a
professional C++ programmer.
I'll buy "understanding". I won't accept "using". Too much
professionally-written C++ code (including some of my own) simply does not
use "const" for you to make that claim.
May 15 '07 #31

P: n/a

"Peter Duniho" <Np*********@nnowslpianmk.comwrote in message
news:op***************@petes-computer.local...
On Tue, 15 May 2007 15:07:56 -0700, Ben Voigt <rb*@nospam.nospamwrote:
>[...]
Understanding and using const-correctness is a prerequisite for being a
professional C++ programmer.

I'll buy "understanding". I won't accept "using". Too much
professionally-written C++ code (including some of my own) simply does not
use "const" for you to make that claim.
And we're already waaaaay off-topic for the C# group.

I'll just say that you'd have to have very specialized code for const not to
be useful. Subsets of C++ used by embedded compilers, perhaps (although in
my experience they overload const and make it mandatory). But string
literals are arrays of const char, so it's *really* hard to do anything
useful without const and maintain any semblance of efficiency.
May 15 '07 #32

P: n/a
On Tue, 15 May 2007 16:37:04 -0700, Ben Voigt <rb*@nospam.nospamwrote:
And we're already waaaaay off-topic for the C# group.
No doubt. It happens. :) At least we're still talking about
programming. :)
I'll just say that you'd have to have very specialized code for const
not to be useful.
"useful" != "mandatory"
[...] But string
literals are arrays of const char, so it's *really* hard to do anything
useful without const and maintain any semblance of efficiency.
Are you saying that failing to use the "const" keyword in C++ causes
performance problems? That's an interesting statement. Care to elaborate?

Pete
May 16 '07 #33

P: n/a
>Are you saying that failing to use the "const" keyword in C++ causes
>performance problems? That's an interesting statement. Care to elaborate?
Well, for the specific case of a string literal, you can do:

const char* psz = "This is a constant string";

or

char[] asz = "This is a non-const literal string";

The second form requires the compiler to actually initialize the memory on
every entry to the function, instead of referencing a string literal. It
also prevents string folding, which increases the size of the binary, which
has its own set of performance problems.

Beyond that, pass-by-const reference is more performant than pass-by-value
for large data types. Sure, you don't strictly need const for that, you can
pass by reference and get most of the performance gains. But, const also
enables a lot of optimizations:

reuse of temporaries
constructor elision
improved alias analysis
elimination of variable access
loop unrolling

For an example:

const int nibbleCount = sizeof (int) * 2;
char formatted[nibbleCount + 1] = { 0 };

char* ToHex(int n)
{
for( int i = 0; i < nibbleCount; i++ )
{
formatted[nibbleCount - i] = 0x30 + ((n >(4 * i)) & 0x0f);
if (formatted[nibbleCount - i] '9') formatted[nibbleCount - i] +=
'a' - '0' - 10;
}
}

Take out the const, and the snippet won't even compile... and if it did, the
compiler couldn't unroll the loop. With a constant value of nibbleCount,
however, the compiler can remove the loop entirely, eliminate the variable
i, and start using specialized instructions for accessing the different
bytes of the input.
May 16 '07 #34

P: n/a
Personall, because of the false positive issue, I think such a warning
isn't a good idea. You'd see it far too often when it wasn't legitimate
for it to actually be useful.
Yes, definitely for C++, since "const" was never really required.

But, for C#, the warning would only come up when you're potentially
modifying a temporary. Usually you don't even want to be calling a
method AT ALL on one, so I don't think the warning would happen too
often when it shouldn't (but that's based on my limited experience).
My feeling is that while it's possible theoretically to address the issue,
I think it's simpler to just make the language simple and consistent, and
require developers to understand that the List<"[]" operator is
providing a copy of the element in the list. There's too many situations
where working directly with the copied value is useful for the compiler to
go around warning you every time you do it, and introducing a "const"
attribute (explicit or implicit) creates far too many new hassles to make
it worth the trouble.
If it happens all the time, and the warning fires false positives,
then yes, it would just be a pain. I didn't think that this would
really ever happen.

Just an idea. ;)

Zytan

May 16 '07 #35

P: n/a
Actually, in a good programmer's hands, that's a notice to the compiler that
the function is not guaranteed to leave the data unchanged. I'd hate for
the compiler to analyze a stub function, make an automatic determination of
const-ness, and somehow affect how the code around it is error-checked.
(Note that optimizing the generated machine code is ok, optimizing away
errors and warnings is not).

Understanding and using const-correctness is a prerequisite for being a
professional C++ programmer. It's an important part of documentation,
compile-time error checking, and enables automatic optimizations that
couldn't otherwise be performed.
I got into this a lot back on the VB group, that there's a lot that
"const" does that people who have never used it would ever realize.
And when I say "used it", i mean actually used it 100% where it should
be used. Without getting into detail, I'll mention just one benefit:
it's forced me to correct large architectural issues that I wasn't
aware of. A lot power in a little word.

I still think C#'s designer's thoughts on how C++'s "const" only works
because it can be cast away is 100% completely false. It's done
nothing but be a benefit for me. (But, perhaps I just haven't seen
the situations he has seen. But, perhaps his situations wouldn't have
happened had "const" been used from the get-go, though. Perhaps an
architectural redesign wasn't worth having "const" in there, so they
cast it away, thinking "const is useless, you have to cast it away to
work", and that's the most likely scenario.)

Zytan

May 16 '07 #36

P: n/a
I think I cover this adequately in the article I just posted, but just for
completeness...
Yes, sorry to continue this in 2 different sections.
The problem (well, "a problem" anyway) is that lots of methods are
essentially "const" even though no one's bothered to mark them as such.
Yes, but you could mark them as "const" when the warning fires.
For that matter, lots of methods are essentially "const" even though they
can't be marked as such, because they might call some other code that is
essentially "const" but which isn't marked as such.
Yes, and this forces you to mark these as "const". And if, finally
you realize at the very end you can't change the last one, since it
ISN'T const, and it should be, and you fix a major design issue.
No, I wouldn't want things to change depending if it had const-ness or
not! It could just be used for a helpful warning, that's all: Why
call a method that changes the class when the class is a temporary,
and is thrown away before you can even see or use it?

Well, a *class* _isn't_ temporary. If you get a reference from a List<>,
then yes you get a copy of the reference, just like you get a copy of a
value type. But the reference refers to a single instance, and if you
change that instance, that change is reflected whether you look at the
copied reference you're using, or the original reference stored in the
List<>.
Sorry, you're right, classes are references, and the 'copy' is the
reference to it, so you still have access to the original. And a
'class' is not a temporary, the reference to it is.

I *meant* to say 'struct' / value type, instead. I'll try to be more
clear in the future.

Zytan

May 16 '07 #37

P: n/a
On Wed, 16 May 2007 06:38:41 -0700, Ben Voigt <rb*@nospam.nospamwrote:
Well, for the specific case of a string literal, you can do:

const char* psz = "This is a constant string";

or

char[] asz = "This is a non-const literal string";
A few things.

First, I was under the impression that we were discussing the "const"
keyword as it applies to function declarations. The above are examples of
"const"-declared constants, which C# does already have, and so aren't
really what we were talking about.

Second, in the above example, the second line of code doesn't compile.
You can fix the syntax error, by putting the [] in the right place (after
the "asz" rather than after the "char"), but then the type of the variable
is not the same as the first line of code. You can't compare the results
of the two, because you're changing more than just the "const"-ness.

Third, if make the two lines of code actually comparable, by fixing the
type in the second line of code to be "char*", you'll find that it
compiles to exactly the same instructions as the first line of code. In
other words, any difference between the two lines of code you posted (once
you fix it so that it compiles) are caused *not* by the use of the "const"
keyword, but rather by the differences in the way the compiler deals with
a pointer versus an array.
The second form requires the compiler to actually initialize the memory
on every entry to the function, instead of referencing a string
literal. It
also prevents string folding, which increases the size of the binary,
which has its own set of performance problems.
See above. Any such problems are not due to the difference between
something being "const" and not "const". (Though, actually...I looked at
the code generated and while it's true the array is initialized
differently than the pointer, that initialization does not actually
involve initializing the storage for the array itself...in other words,
it's not like the string literal gets copied).
Beyond that, pass-by-const reference is more performant than
pass-by-value for large data types. Sure, you don't strictly need
const for that, you can pass by reference and get most of the
performance gains.
You don't even not strictly need const for that. The use of the "const"
keyword has nothing do with whether you can pass things by reference or
not. It makes it safer (which *is* the point of using "const"), but you
can pass things by reference just fine without using "const". In other
words, in that example, "const" doesn't improve performance, it improves
safety.

I certainly wouldn't try to disagree with the statement that "const"
improves safety. But that's not the question here.
But, const also enables a lot of optimizations:

reuse of temporaries
constructor elision
improved alias analysis
elimination of variable access
loop unrolling
As applied to function declarations, I don't see how "const" enables any
of those optimizations. The compiler can't rely on the "const" keyword,
because it can always wind up being cast away.
For an example:

const int nibbleCount = sizeof (int) * 2;
char formatted[nibbleCount + 1] = { 0 };

char* ToHex(int n)
{
for( int i = 0; i < nibbleCount; i++ )
{
formatted[nibbleCount - i] = 0x30 + ((n >(4 * i)) & 0x0f);
if (formatted[nibbleCount - i] '9') formatted[nibbleCount - i] +=
'a' - '0' - 10;
}
}
Take out the const, and the snippet won't even compile... and if it did,
the compiler couldn't unroll the loop. With a constant value of
nibbleCount,
however, the compiler can remove the loop entirely, eliminate the
variable i, and start using specialized instructions for accessing the
different
bytes of the input.
Well, first of all, that code won't compile regardless. You've got a
function that is supposed to return a value, but it doesn't.

Secondly, the reason taking "const" out prevents it from compiling is that
you can't initialize an array with a size that isn't known at compile
time. And of course, likewise the compiler can't make optimizations
requiring constant values based on non-constant values.

For example, these two functions wind up compiled to be very different:

const int i = 5;
void Test1()
{
printf("%d", i);
}

int j = 5;
void Test2()
{
printf("%d", j);
}

I certainly don't debate that. But the reason they are different is
because in the first case, the value of the variable is known at compile
time, while the value of the variable in the second case is not. This has
exactly nothing to do with the question of using "const" in a function
declaration.

I thought maybe you had an example of how including "const" for function
declarations in C# would help optimizations. After all, C# already has
"const" for variable declarations, and it has the same benefits in C# as
it has in C++. So there's not really any point in contrasting the two
languages in that way. So far, you haven't provided any actual examples
of performance improvements that using "const" in a function declaration
would enable.

Pete
May 16 '07 #38

P: n/a
On Wed, 16 May 2007 09:12:34 -0700, Zytan <zy**********@gmail.comwrote:
[...]
But, for C#, the warning would only come up when you're potentially
modifying a temporary. Usually you don't even want to be calling a
method AT ALL on one, so I don't think the warning would happen too
often when it shouldn't (but that's based on my limited experience).
I disagree that you would never want to call a method on a temporary
value. In fact, because of the OOP nature of C#, you are almost always
calling a method, if you are using a temporary value at all.

If anything, I could see adding a warning when you are modifying a public
field of a value type that is a temporary instance. That seems obviously
unwise and reasonable for the compiler to complain. But for methods, the
method could be doing anything, and the compiler doesn't really know what
that is. In fact, for a well-designed value type (eg immutable), a method
on a value type would *always* be safe on a temporary value.

Pete
May 16 '07 #39

P: n/a
On Wed, 16 May 2007 09:23:09 -0700, Zytan <zy**********@gmail.comwrote:
>The problem (well, "a problem" anyway) is that lots of methods are
essentially "const" even though no one's bothered to mark them as such.

Yes, but you could mark them as "const" when the warning fires.
Been there, done that. In any sizable project, you can waste a whole day
chasing down warnings and still not find all the places you need to add
"const".

And even when you spend that time, frequently you reach a point where
you're calling some third-party API that you don't have the freedom to
change. At that point, if the language doesn't allow you to cast away
const-ness, you're stuck. And allowing you to cast away const-ness
significantly lessens the usefulness of "const", IMHO.
Yes, and this forces you to mark these as "const". And if, finally
you realize at the very end you can't change the last one, since it
ISN'T const, and it should be, and you fix a major design issue.
What do you do when you don't have control over the design that is causing
you trouble?
No, I wouldn't want things to change depending if it had const-ness or
not! It could just be used for a helpful warning, that's all: Why
call a method that changes the class when the class is a temporary,
and is thrown away before you can even see or use it?
[...]

I *meant* to say 'struct' / value type, instead. I'll try to be more
clear in the future.
Okay...well, I can agree that calling a method that changes a struct when
the struct is temporary isn't useful. But how to implement this in a
practical way is the question.

Pete
May 16 '07 #40

P: n/a
Sorry about not compile-testing.

Here is an example that may work better for you:

/* in one compilation unit */
namespace { std::vector<intv; }
void stuffit(int& n)
{
v.push_back(n);
}

/* in another compilation unit, assuming that the proper prototype for
stuffit is available */
int main()
{
for( int i = 0; i < 4; i++ ) {
stuffit(i);
}
return 0;
}

Without "const", no optimizations are possible. With "const int& n", the
compiler can fully unroll the loop and eliminate i. Yes, I know that
passing an int by const reference in this case is silly, but it could easily
be a large data structure, and stuffit could be an arbitrary level of
complexity.

Or:

void demo(int i)
{
int a[10];
for( int j = 0; j < 10000; j++ )
{
a[13 * i % 7 + 3] += j;
stuffit(i);
}
}

With "const int& n", the compiler can determine that i is unchanging for the
duration of the loop, and by extension, the pointer a + 13 * i % 7 + 3 can
be pre-computed (and in fact the entire addition operation could be
pre-evaluated as 10000 * 10001 / 2 =50005000). Without "const", aliasing
analysis reveals that i can change, therefore the computation must be
executed inside the loop, with little opportunity for optimization.

And the const on a member function is equivalent to changing constness of
the 'this' parameter, so all the above applies.
May 17 '07 #41

P: n/a
>
>As applied to function declarations, I don't see how "const" enables any
of those optimizations. The compiler can't rely on the "const" keyword,
because it can always wind up being cast away.
I absolutely disagree with this. The onus is on the programmer not to cast
away const in any way that would make the compiler's optimizations incorrect
which rely on said const-ness. Practically speaking, casting away const is
always an error, now that C++ has the mutable keyword. But certainly the
compiler can and does rely on the const keyword, and you take your (process)
life in your hands when you cast it away.
May 17 '07 #42

P: n/a

"Peter Duniho" <Np*********@nnowslpianmk.comwrote in message
news:op***************@petes-computer.local...
On Wed, 16 May 2007 09:12:34 -0700, Zytan <zy**********@gmail.comwrote:
>[...]
But, for C#, the warning would only come up when you're potentially
modifying a temporary. Usually you don't even want to be calling a
method AT ALL on one, so I don't think the warning would happen too
often when it shouldn't (but that's based on my limited experience).

I disagree that you would never want to call a method on a temporary
value. In fact, because of the OOP nature of C#, you are almost always
calling a method, if you are using a temporary value at all.

If anything, I could see adding a warning when you are modifying a public
field of a value type that is a temporary instance. That seems obviously
unwise and reasonable for the compiler to complain. But for methods, the
method could be doing anything, and the compiler doesn't really know what
that is. In fact, for a well-designed value type (eg immutable), a method
on a value type would *always* be safe on a temporary value.
And an immutable value type would only have methods declared const, so
safety is properly noted by the compiler.
>
Pete

May 17 '07 #43

P: n/a

"Peter Duniho" <Np*********@nnowslpianmk.comwrote in message
news:op***************@petes-computer.local...
On Wed, 16 May 2007 09:23:09 -0700, Zytan <zy**********@gmail.comwrote:
>>The problem (well, "a problem" anyway) is that lots of methods are
essentially "const" even though no one's bothered to mark them as such.

Yes, but you could mark them as "const" when the warning fires.

Been there, done that. In any sizable project, you can waste a whole day
chasing down warnings and still not find all the places you need to add
"const".

And even when you spend that time, frequently you reach a point where
you're calling some third-party API that you don't have the freedom to
change. At that point, if the language doesn't allow you to cast away
And that impeaches the design of said API and should seriously call into
question your decision to use it. If a library designer can't get
const-correctness, how can they be expected to properly solve a bunch of
more devious concerns (parameter checking, buffer overflows, race
conditions, etc)?

const-ness, you're stuck. And allowing you to cast away const-ness
significantly lessens the usefulness of "const", IMHO.
>Yes, and this forces you to mark these as "const". And if, finally
you realize at the very end you can't change the last one, since it
ISN'T const, and it should be, and you fix a major design issue.

What do you do when you don't have control over the design that is causing
you trouble?
You let your boss know that the design has fundamental flaws, and be
thankful that const brought these to your attention before deploying said
flawed design in a critical scenario and maybe killing someone.
>
>No, I wouldn't want things to change depending if it had const-ness or
not! It could just be used for a helpful warning, that's all: Why
call a method that changes the class when the class is a temporary,
and is thrown away before you can even see or use it?
[...]

I *meant* to say 'struct' / value type, instead. I'll try to be more
clear in the future.

Okay...well, I can agree that calling a method that changes a struct when
the struct is temporary isn't useful. But how to implement this in a
practical way is the question.

Pete

May 17 '07 #44

P: n/a
On Thu, 17 May 2007 07:41:27 -0700, Ben Voigt <rb*@nospam.nospamwrote:
>And even when you spend that time, frequently you reach a point where
you're calling some third-party API that you don't have the freedom to
change. At that point, if the language doesn't allow you to cast away

And that impeaches the design of said API and should seriously call into
question your decision to use it.
You mean, like the Windows API?

I suppose I could avoid writing Windows software, but...that severely
restricts my market.

Pete
May 17 '07 #45

P: n/a

"Peter Duniho" <Np*********@nnowslpianmk.comwrote in message
news:op***************@petes-computer.local...
On Thu, 17 May 2007 07:41:27 -0700, Ben Voigt <rb*@nospam.nospamwrote:
>>And even when you spend that time, frequently you reach a point where
you're calling some third-party API that you don't have the freedom to
change. At that point, if the language doesn't allow you to cast away

And that impeaches the design of said API and should seriously call into
question your decision to use it.

You mean, like the Windows API?
You're going to have to be far more specific -- there are a lot of different
libraries grouped under the heading of "the Windows API" and all the core
ones are const-correct, in my experience.

If you find a Windows API function that isn't const-correct, then yes, I
would avoid that library and re-implement the required functionality using
the core APIs (or find a solution that has already done so, in a trustworthy
manner).
>
I suppose I could avoid writing Windows software, but...that severely
restricts my market.

Pete

May 17 '07 #46

This discussion thread is closed

Replies have been disabled for this discussion.