Note
----
Please use a fixed-width font to view this, such as Courier New.
Problem
-------
When passing a parameter with the modifier 'out', it is necessary to
write two statements:
- one for the declaration of the variable due to receive the value; and
- one for the method call, where the variable is passed as a parameter.
Example:
static void Main()
{
int i;
if (TryGetValue(out i)) {
Console.WriteLine("Value is: {0}.", i);
}
}
This is inconsistent with the traditional way of returning values from a
method.
Example:
static void Main()
{
int i = GetValue();
Console.WriteLine("Value is: {0}.", i);
}
Solution
--------
The solution to this problem would be to allow the declaration of the
variable to appear within the statment where it's being passed as an
'out' parameter.
Example:
static void Main()
{
if (TryGetValue(out int i)) {
Console.WriteLine("Value is: {0}.", i);
}
}
Benefits
--------
(a) Method bodies can benefit from one less statement for each time this
technique is used, promoting readability.
(b) C# becomes more consistent since returning values using both the
traditional way, and using 'out' parameters, is uniform. Again,
this promotes readability.
Example:
// traditional way
static void Main()
{
int i = GetANumber();
DoSomethingWith(i);
}
// using an 'out' parameter, with the aforementioned syntax
static void Main()
{
if (TryGetANumber(out int i)) {
DoSomethingWith(i);
}
}
End
---
Comments?
Regards,
C. S. Learner 24 1565
I have a better proposal for ref and out:
instead of using "pass by reference" semantics, why not use
"copyin/copyout" semantics for "ref" and "copyout"semantics for "out".
This way, you would not need to declare a variable every time. In lots of
cases, you would be able to receive the value directly into an object
property. For example:
if (TryGetValue(myObj.MyProp))
{
// doSomething
}
This would be equivalent (almost) to the following that you have to write
today:
int i;
if (TryGetValue(out i))
{
myObj.MyProp = i;
}
For a "ref" (in/out) parameter, the gain is even more obvious. It would save
both the assignment from the property to a temp variable before the call,
and the reverse assignment after the call.
Also, I understand why "ref" and "out" are needed in the method declaration,
but it seems superfluous to have to specify them at every call.
The last refinement would be to have normal parameters (no keyword, "in"
semantics) be "readonly" inside the method body (you can do this in Java by
marking them with "final"). Of course this is probably too far fetched as it
goes against the C/C++/Java tradition, but IMO, this is so much cleaner and
would make the language easier to understand to beginners (for once,
mimicking Pascal or ADA rather than C++ would help).
Just some ideas...
Bruno.
"C# Learner" <cs****@learner.here> a écrit dans le message de
news:ew**************@TK2MSFTNGP10.phx.gbl... Note ----
Please use a fixed-width font to view this, such as Courier New.
Problem -------
When passing a parameter with the modifier 'out', it is necessary to write two statements:
- one for the declaration of the variable due to receive the value; and - one for the method call, where the variable is passed as a parameter.
Example:
static void Main() { int i; if (TryGetValue(out i)) { Console.WriteLine("Value is: {0}.", i); } }
This is inconsistent with the traditional way of returning values from a method.
Example:
static void Main() { int i = GetValue(); Console.WriteLine("Value is: {0}.", i); }
Solution --------
The solution to this problem would be to allow the declaration of the variable to appear within the statment where it's being passed as an 'out' parameter.
Example:
static void Main() { if (TryGetValue(out int i)) { Console.WriteLine("Value is: {0}.", i); } }
Benefits --------
(a) Method bodies can benefit from one less statement for each time this technique is used, promoting readability.
(b) C# becomes more consistent since returning values using both the traditional way, and using 'out' parameters, is uniform. Again, this promotes readability.
Example:
// traditional way static void Main() { int i = GetANumber(); DoSomethingWith(i); }
// using an 'out' parameter, with the aforementioned syntax static void Main() { if (TryGetANumber(out int i)) { DoSomethingWith(i); } }
End ---
Comments?
Regards, C. S. Learner
"C# Learner" <cs****@learner.here> wrote: [proposed new syntax] if (TryGetValue(out int i))
I'd appreciate that. It seems no more problematic than being able to declare
a loop counter variable within a for statement.
P.
>Also, I understand why "ref" and "out" are needed in the method
declaration, but it seems superfluous to have to specify them at every call.
i think it makes the code more understandable, for example while debugging
you wont have to goto to see the method declaration to find out if the
parameter was a ref or out, instead you'll know right there and then from
the call what the methods accepts.
"Bruno Jouhier [MVP]" <bj******@club-internet.fr> wrote in message
news:Oc**************@TK2MSFTNGP09.phx.gbl... I have a better proposal for ref and out:
instead of using "pass by reference" semantics, why not use "copyin/copyout" semantics for "ref" and "copyout"semantics for "out".
This way, you would not need to declare a variable every time. In lots of cases, you would be able to receive the value directly into an object property. For example:
if (TryGetValue(myObj.MyProp)) { // doSomething }
This would be equivalent (almost) to the following that you have to write today:
int i; if (TryGetValue(out i)) { myObj.MyProp = i; }
For a "ref" (in/out) parameter, the gain is even more obvious. It would
save both the assignment from the property to a temp variable before the call, and the reverse assignment after the call.
Also, I understand why "ref" and "out" are needed in the method
declaration, but it seems superfluous to have to specify them at every call.
The last refinement would be to have normal parameters (no keyword, "in" semantics) be "readonly" inside the method body (you can do this in Java
by marking them with "final"). Of course this is probably too far fetched as
it goes against the C/C++/Java tradition, but IMO, this is so much cleaner
and would make the language easier to understand to beginners (for once, mimicking Pascal or ADA rather than C++ would help).
Just some ideas...
Bruno. "C# Learner" <cs****@learner.here> a écrit dans le message de news:ew**************@TK2MSFTNGP10.phx.gbl... Note ----
Please use a fixed-width font to view this, such as Courier New.
Problem -------
When passing a parameter with the modifier 'out', it is necessary to write two statements:
- one for the declaration of the variable due to receive the value; and - one for the method call, where the variable is passed as a parameter.
Example:
static void Main() { int i; if (TryGetValue(out i)) { Console.WriteLine("Value is: {0}.", i); } }
This is inconsistent with the traditional way of returning values from a method.
Example:
static void Main() { int i = GetValue(); Console.WriteLine("Value is: {0}.", i); }
Solution --------
The solution to this problem would be to allow the declaration of the variable to appear within the statment where it's being passed as an 'out' parameter.
Example:
static void Main() { if (TryGetValue(out int i)) { Console.WriteLine("Value is: {0}.", i); } }
Benefits --------
(a) Method bodies can benefit from one less statement for each time this technique is used, promoting readability.
(b) C# becomes more consistent since returning values using both the traditional way, and using 'out' parameters, is uniform. Again, this promotes readability.
Example:
// traditional way static void Main() { int i = GetANumber(); DoSomethingWith(i); }
// using an 'out' parameter, with the aforementioned syntax static void Main() { if (TryGetANumber(out int i)) { DoSomethingWith(i); } }
End ---
Comments?
Regards, C. S. Learner
"Bruno Jouhier [MVP]" <bj******@club-internet.fr> wrote: [...] I understand why "ref" and "out" are needed in the method declaration, but it seems superfluous to have to specify them at every call.
I think it's good to be able to see which parameters might be changed
without having to examine the function being called.
P.
Bruno Jouhier [MVP] <bj******@club-internet.fr> wrote: Also, I understand why "ref" and "out" are needed in the method declaration, but it seems superfluous to have to specify them at every call.
Aargh no! It's absolutely *vital* to my mind that you should specify
them at every call - otherwise it's far from obvious, unless you look
at the declaration of what you're calling, that the parameter is being
passed by reference. I for one don't want to have to check the
declaration of every method which is called just in order to know
what's going on.
Ref/out are (or should be, IMO) rarely enough used that it's not like
it's going to take that many more keystrokes anyway, and the difference
in readability is huge.
--
Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
"Jon Skeet [C# MVP]" <sk***@pobox.com> skrev i meddelandet
news:MP************************@msnews.microsoft.c om... Bruno Jouhier [MVP] <bj******@club-internet.fr> wrote: Also, I understand why "ref" and "out" are needed in the method
declaration, but it seems superfluous to have to specify them at every call. Aargh no! It's absolutely *vital* to my mind that you should specify them at every call - otherwise it's far from obvious, unless you look at the declaration of what you're calling, that the parameter is being passed by reference. I for one don't want to have to check the declaration of every method which is called just in order to know what's going on.
Ref/out are (or should be, IMO) rarely enough used that it's not like it's going to take that many more keystrokes anyway, and the difference in readability is huge.
I second that.
-- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet If replying to the group, please do not mail me too
> (a) Method bodies can benefit from one less statement for each time this technique is used, promoting readability.
(b) C# becomes more consistent since returning values using both the traditional way, and using 'out' parameters, is uniform. Again, this promotes readability.
Example:
// traditional way static void Main() { int i = GetANumber(); DoSomethingWith(i); }
// using an 'out' parameter, with the aforementioned syntax static void Main() { if (TryGetANumber(out int i)) { DoSomethingWith(i); } }
End ---
Comments?
The primary problem I have with this is in all othercases I can think of, a
variable declared within a () is scoped to the underlying block(method
parameters, for (int x) { //x is only valid here }, using (IDisposable x)
{ //x is only valid here }. By allowing declarations within a method call,
you remove that partciular consistence of the language. Regards, C. S. Learner
Daniel O'Connell [C# MVP] wrote: Comments?
The primary problem I have with this is in all othercases I can think of, a variable declared within a () is scoped to the underlying block(method parameters, for (int x) { //x is only valid here }, using (IDisposable x) { //x is only valid here }. By allowing declarations within a method call, you remove that partciular consistence of the language.
Hmm, good point. Back to the drawing board then.
"C# Learner" <cs****@learner.here> wrote in message
news:ut**************@TK2MSFTNGP11.phx.gbl... Daniel O'Connell [C# MVP] wrote:
Comments?
The primary problem I have with this is in all othercases I can think of, a variable declared within a () is scoped to the underlying block(method parameters, for (int x) { //x is only valid here }, using (IDisposable x) { //x is only valid here }. By allowing declarations within a method call, you remove that partciular consistence of the language.
Hmm, good point. Back to the drawing board then.
You'll find yourself doing that *alot* when trying to get syntax down. The
first forty ideas or so rarely seem to work, ;)
Ok. Maybe the few additional keystrokes are worth it. At least many people
seem to react strongly here.
If I remember well, languages like Pascal and ADA support in/out parameters
and you only need to specify this in the function/procedure declaration, you
don't repeat it every time you call. Also, seems to me that the method name
or the parameter name should give a good hint about the in/out nature of the
parameter. This is why I suggested that they are not that useful on the
caller side.
Also, I still do most of my developments in Java (or rather J#). So, I still
have to fight with the lack of goodies like in/out parameters :-(. So you
guys probably know better.
But I think that the debate around "by reference" semantics vs.
"copyin/copyout" semantics is interesting, and I don't really understand why
the C# (or rather .NET) designers did not choose copyin/copyout. In general
they made very good language design choices, but here, I think that they
made a rather poor choice.
Bruno.
"Jon Skeet [C# MVP]" <sk***@pobox.com> a écrit dans le message de
news:MP************************@msnews.microsoft.c om... Bruno Jouhier [MVP] <bj******@club-internet.fr> wrote: Also, I understand why "ref" and "out" are needed in the method
declaration, but it seems superfluous to have to specify them at every call.
Aargh no! It's absolutely *vital* to my mind that you should specify them at every call - otherwise it's far from obvious, unless you look at the declaration of what you're calling, that the parameter is being passed by reference. I for one don't want to have to check the declaration of every method which is called just in order to know what's going on.
Ref/out are (or should be, IMO) rarely enough used that it's not like it's going to take that many more keystrokes anyway, and the difference in readability is huge.
-- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet If replying to the group, please do not mail me too
Bruno Jouhier [MVP] <bj******@club-internet.fr> wrote: Ok. Maybe the few additional keystrokes are worth it. At least many people seem to react strongly here.
If I remember well, languages like Pascal and ADA support in/out parameters and you only need to specify this in the function/procedure declaration, you don't repeat it every time you call.
And C# has learned from the mistakes of the past :)
Also, seems to me that the method name or the parameter name should give a good hint about the in/out nature of the parameter. This is why I suggested that they are not that useful on the caller side.
I don't believe it's always obvious, to be honest.
Also, I still do most of my developments in Java (or rather J#). So, I still have to fight with the lack of goodies like in/out parameters :-(. So you guys probably know better.
Personally I don't really regard ref and out parameters as "goodies".
They're necessary evils for interop, but I try to keep them out of my
code wherever possible. Then again, I have a Java background as well.
But I think that the debate around "by reference" semantics vs. "copyin/copyout" semantics is interesting, and I don't really understand why the C# (or rather .NET) designers did not choose copyin/copyout. In general they made very good language design choices, but here, I think that they made a rather poor choice.
I'm not sure I particularly mind that much - what are the benefits of
copyin/copyout, here?
--
Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
> > But I think that the debate around "by reference" semantics vs. "copyin/copyout" semantics is interesting, and I don't really understand
why the C# (or rather .NET) designers did not choose copyin/copyout. In
general they made very good language design choices, but here, I think that they made a rather poor choice.
I'm not sure I particularly mind that much - what are the benefits of copyin/copyout, here?
The main benefit of copyin/copyout is that you can pass any valid
assignement LHS as in/out argument. In particular, you can pass an object
property and indexed expression, etc. For example, instead of having to
write:
int val = obj.Prop;
if (GetNewValue(ref val)) {
obj.Prop = val;
// more stuff
}
You just need to write:
if (GetNewValue(inout obj.Prop)) {
// more stuff
}
This is more concise, easier to read, and just as efficient.
Bruno.
"Bruno Jouhier [MVP]" <bj******@club-internet.fr> wrote in message
news:%2***************@TK2MSFTNGP12.phx.gbl... > But I think that the debate around "by reference" semantics vs. > "copyin/copyout" semantics is interesting, and I don't really > understand why > the C# (or rather .NET) designers did not choose copyin/copyout. In general > they made very good language design choices, but here, I think that > they > made a rather poor choice.
I'm not sure I particularly mind that much - what are the benefits of copyin/copyout, here?
The main benefit of copyin/copyout is that you can pass any valid assignement LHS as in/out argument. In particular, you can pass an object property and indexed expression, etc. For example, instead of having to write:
int val = obj.Prop; if (GetNewValue(ref val)) { obj.Prop = val; // more stuff }
You just need to write:
if (GetNewValue(inout obj.Prop)) { // more stuff }
This is more concise, easier to read, and just as efficient.
Though, one may argue it basically provides the ability to do something that
you would probably never be able to justify doing. Passing a property(or a
field, even though its allowed) to a ref parameter is a very bad idea, IMHO.
If a non-essential method with a ref fails, the value of that ref is
undefined as far as I'm concerned. Allowing that to be extended to
properties is horrible. The syntactical changes that would be needed to
allow you to escape a method without performing the copy out is unpleasent.
Not providing any syntax in effect allows a failed method call to corrupt
the object's state and would make the exception\error handling code and the
code with the ref\out parameter have the nasty stuff instead of the standard
path. You can't just forget about the value of a property like you can with
a local, you have to take the time and back up the value if its at all
possible the method could fail.
You potentially end up with:
int val = obj.Prop
if (GetNewVal(inout obj.Prop))
{
//more stuff
}
else
{
obj.Prop = val;
}
or
int val = obj.Prop
try
{
GetNewVal(inout obj.Prop);
//more stuff
}
catch (WhateverException)
{
obj.Prop = val;
}
catch (WhateverOtherException)
{
obj.Prop = val;
}
catch (AnotherExceptionException)
{
//Again!
//makes me wish C# had fault handlers, I'd not have to write this so
much
obj.Prop = val;
}
finally
{
//do whatever
}
why is that better?
You got it wrong. There is no issue about corrupted state or anything like
that. Maybe you are confusing "copyin/copyout" with "passing by name".
The semantics of copyin/copyout are the following:
With a method declaration like:
MyMethod(inout MyType param)
A call like
MyMethod(inout expression);
is equivalent to:
MyType tmpVar = expression;
MyMethod(ref tmpVar);
expression = tmpVar;
This is actually cleaner than passing by reference because the inout
parameters behave exactly like return values (a ref parameter does not!). If
an exception is thrown by the method, the "copyout" assignment is **not**
performed and the expression is not assigned at all. So, I don't see where
there is a risk of corrupting the object state here. On the other hand, all
this seems very safe.
Passing "by name" is another story, and I would not advocate for it at all,
at least as a general passing mechanism. It has horrible side effects.
Bruno.
"Daniel O'Connell [C# MVP]" <onyxkirx@--NOSPAM--comcast.net> a écrit dans le
message de news:Oc*************@TK2MSFTNGP12.phx.gbl... "Bruno Jouhier [MVP]" <bj******@club-internet.fr> wrote in message news:%2***************@TK2MSFTNGP12.phx.gbl... > But I think that the debate around "by reference" semantics vs. > "copyin/copyout" semantics is interesting, and I don't really > understand why > the C# (or rather .NET) designers did not choose copyin/copyout. In general > they made very good language design choices, but here, I think that > they > made a rather poor choice.
I'm not sure I particularly mind that much - what are the benefits of copyin/copyout, here?
The main benefit of copyin/copyout is that you can pass any valid assignement LHS as in/out argument. In particular, you can pass an
object property and indexed expression, etc. For example, instead of having to write:
int val = obj.Prop; if (GetNewValue(ref val)) { obj.Prop = val; // more stuff }
You just need to write:
if (GetNewValue(inout obj.Prop)) { // more stuff }
This is more concise, easier to read, and just as efficient.
Though, one may argue it basically provides the ability to do something
that you would probably never be able to justify doing. Passing a property(or a field, even though its allowed) to a ref parameter is a very bad idea,
IMHO. If a non-essential method with a ref fails, the value of that ref is undefined as far as I'm concerned. Allowing that to be extended to properties is horrible. The syntactical changes that would be needed to allow you to escape a method without performing the copy out is
unpleasent. Not providing any syntax in effect allows a failed method call to corrupt the object's state and would make the exception\error handling code and
the code with the ref\out parameter have the nasty stuff instead of the
standard path. You can't just forget about the value of a property like you can
with a local, you have to take the time and back up the value if its at all possible the method could fail. You potentially end up with: int val = obj.Prop if (GetNewVal(inout obj.Prop)) { //more stuff } else { obj.Prop = val; }
or int val = obj.Prop try { GetNewVal(inout obj.Prop); //more stuff } catch (WhateverException) { obj.Prop = val; } catch (WhateverOtherException) { obj.Prop = val; } catch (AnotherExceptionException) { //Again! //makes me wish C# had fault handlers, I'd not have to write this so much obj.Prop = val; } finally { //do whatever }
why is that better?
Bruno Jouhier [MVP] <bj******@club-internet.fr> wrote: The main benefit of copyin/copyout is that you can pass any valid assignement LHS as in/out argument. In particular, you can pass an object property and indexed expression, etc. For example, instead of having to write:
int val = obj.Prop; if (GetNewValue(ref val)) { obj.Prop = val; // more stuff }
You just need to write:
if (GetNewValue(inout obj.Prop)) { // more stuff }
This is more concise, easier to read, and just as efficient.
Right. That makes sense - and presumably you could also have just
output parameters where the property isn't read to start with, it's
only written out at the end?
Interestingly enough, VB.NET allows you to specify properties as ByRef
parameters, which does exactly the above. Now, I hate the fact that it
does it silently, but if a parameter could actually be *declared* that
way, it would make an awful lot of sense.
--
Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
> Right. That makes sense - and presumably you could also have just output parameters where the property isn't read to start with, it's only written out at the end?
Yes, of course, it also works for "out", this is simply "copyout" argument
passing.
BTW, copyout is what comes closest to multiple returns (the assignment is
done after the method returns), and, as my response to Daniel explains,
there is no special problem if the method throws an exception, the copyout
assignment is not performed, the same way the "normal" return value is not
assigned.
Bruno. Interestingly enough, VB.NET allows you to specify properties as ByRef parameters, which does exactly the above. Now, I hate the fact that it does it silently, but if a parameter could actually be *declared* that way, it would make an awful lot of sense.
"Bruno Jouhier [MVP]" <bj******@club-internet.fr> wrote in message
news:O$**************@TK2MSFTNGP11.phx.gbl... You got it wrong. There is no issue about corrupted state or anything like that. Maybe you are confusing "copyin/copyout" with "passing by name".
The semantics of copyin/copyout are the following:
With a method declaration like: MyMethod(inout MyType param)
A call like MyMethod(inout expression);
is equivalent to: MyType tmpVar = expression; MyMethod(ref tmpVar); expression = tmpVar;
This is actually cleaner than passing by reference because the inout parameters behave exactly like return values (a ref parameter does not!). If an exception is thrown by the method, the "copyout" assignment is **not** performed and the expression is not assigned at all. So, I don't see where there is a risk of corrupting the object state here. On the other hand, all this seems very safe.
I hadn't considered that the code may be generated *around* the method, but
in, which helps mitigate much of the problem(not entirely sure why I was
thinking that way...3am responses aren't always well thought out, ;). The
problem still stands that you would have to throw an exception to stop that
copyout from happening. Your example itself uses an if block to determine
success, how do you escape without throwing an exception?
Passing "by name" is another story, and I would not advocate for it at all, at least as a general passing mechanism. It has horrible side effects.
Bruno.
"Daniel O'Connell [C# MVP]" <onyxkirx@--NOSPAM--comcast.net> a écrit dans le message de news:Oc*************@TK2MSFTNGP12.phx.gbl... "Bruno Jouhier [MVP]" <bj******@club-internet.fr> wrote in message news:%2***************@TK2MSFTNGP12.phx.gbl... >> > But I think that the debate around "by reference" semantics vs. >> > "copyin/copyout" semantics is interesting, and I don't really >> > understand > why >> > the C# (or rather .NET) designers did not choose copyin/copyout. In > general >> > they made very good language design choices, but here, I think that >> > they >> > made a rather poor choice. >> >> I'm not sure I particularly mind that much - what are the benefits of >> copyin/copyout, here? > > The main benefit of copyin/copyout is that you can pass any valid > assignement LHS as in/out argument. In particular, you can pass an object > property and indexed expression, etc. For example, instead of having to > write: > > int val = obj.Prop; > if (GetNewValue(ref val)) { > obj.Prop = val; > // more stuff > } > > You just need to write: > > if (GetNewValue(inout obj.Prop)) { > // more stuff > } > > This is more concise, easier to read, and just as efficient. >
Though, one may argue it basically provides the ability to do something
that you would probably never be able to justify doing. Passing a property(or a field, even though its allowed) to a ref parameter is a very bad idea, IMHO. If a non-essential method with a ref fails, the value of that ref is undefined as far as I'm concerned. Allowing that to be extended to properties is horrible. The syntactical changes that would be needed to allow you to escape a method without performing the copy out is unpleasent. Not providing any syntax in effect allows a failed method call to corrupt the object's state and would make the exception\error handling code and the code with the ref\out parameter have the nasty stuff instead of the standard path. You can't just forget about the value of a property like you can with a local, you have to take the time and back up the value if its at all possible the method could fail. You potentially end up with: int val = obj.Prop if (GetNewVal(inout obj.Prop)) { //more stuff } else { obj.Prop = val; }
or int val = obj.Prop try { GetNewVal(inout obj.Prop); //more stuff } catch (WhateverException) { obj.Prop = val; } catch (WhateverOtherException) { obj.Prop = val; } catch (AnotherExceptionException) { //Again! //makes me wish C# had fault handlers, I'd not have to write this so much obj.Prop = val; } finally { //do whatever }
why is that better?
See inline..
Bruno Jouhier [MVP] wrote: Ok. Maybe the few additional keystrokes are worth it. At least many people seem to react strongly here.
If I remember well, languages like Pascal and ADA support in/out parameters and you only need to specify this in the function/procedure declaration, you don't repeat it every time you call. Also, seems to me that the method name or the parameter name should give a good hint about the in/out nature of the parameter. This is why I suggested that they are not that useful on the caller side.
I would disagree here. IMHO, the ref and out in the calling
function, helps catch wrong usage of functions at compile time. In large
code bases it would potentially save someone a huge amount of debugging
time Also, I still do most of my developments in Java (or rather J#). So, I still have to fight with the lack of goodies like in/out parameters :-(. So you guys probably know better.
But I think that the debate around "by reference" semantics vs. "copyin/copyout" semantics is interesting, and I don't really understand why the C# (or rather .NET) designers did not choose copyin/copyout. In general they made very good language design choices, but here, I think that they made a rather poor choice.
Bruno.
"Jon Skeet [C# MVP]" <sk***@pobox.com> a écrit dans le message de news:MP************************@msnews.microsoft.c om...
Bruno Jouhier [MVP] <bj******@club-internet.fr> wrote:
Also, I understand why "ref" and "out" are needed in the method declaration, but it seems superfluous to have to specify them at every call.
Aargh no! It's absolutely *vital* to my mind that you should specify them at every call - otherwise it's far from obvious, unless you look at the declaration of what you're calling, that the parameter is being passed by reference. I for one don't want to have to check the declaration of every method which is called just in order to know what's going on.
Ref/out are (or should be, IMO) rarely enough used that it's not like it's going to take that many more keystrokes anyway, and the difference in readability is huge.
-- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet If replying to the group, please do not mail me too
--
Regards,
Dilip Krishnan
MCAD, MCSD.net
dilipdotnet at apdiya dot com
> I hadn't considered that the code may be generated *around* the method,
but in, which helps mitigate much of the problem(not entirely sure why I was thinking that way...3am responses aren't always well thought out, ;). The problem still stands that you would have to throw an exception to stop
that copyout from happening. Your example itself uses an if block to determine success, how do you escape without throwing an exception?
If the code is generated "in", as if the parameter was replaced by the
expression every time it appears in the body, this is called passing "by
name", and I would be very strongly against it.
I still don't understand your issue and why a special exception would be
required. I see two cases:
"inout" parameter: the method body may or may not reassign the inout
parameter. If the method completes "normally" (without throwing the
exception), the copyout will assign the last value of the parameter. If the
parameter has not been reassigned inside the method body, nothing really
terrible happens (the unmodified value is reassigned -- a variant would be
to prevent the copy out operation in this case to avoid potential side
effects but this makes code generation a bit more complex for the method
body -- even in the second case, I don't see why an exception is needed,
this can be done with a simple flag, and even by a static analysis at
compile time in most cases).
"out" parameter: here the compiler must check that all execution paths
assign a value to the "out" parameter inside the method body (unless they
throw an exception of course), the same way it checks that all execution
paths return a value if the method has a non void return type. Here, if the
method returns "normally", it must assign a value to "out" parameter.
Bruno.
"Bruno Jouhier [MVP]" <bj******@club-internet.fr> wrote in message
news:%2****************@tk2msftngp13.phx.gbl... I hadn't considered that the code may be generated *around* the method, but in, which helps mitigate much of the problem(not entirely sure why I was thinking that way...3am responses aren't always well thought out, ;). The problem still stands that you would have to throw an exception to stop that copyout from happening. Your example itself uses an if block to determine success, how do you escape without throwing an exception?
If the code is generated "in", as if the parameter was replaced by the expression every time it appears in the body, this is called passing "by name", and I would be very strongly against it.
I still don't understand your issue and why a special exception would be required. I see two cases:
"inout" parameter: the method body may or may not reassign the inout parameter. If the method completes "normally" (without throwing the exception), the copyout will assign the last value of the parameter. If the parameter has not been reassigned inside the method body, nothing really terrible happens (the unmodified value is reassigned -- a variant would be to prevent the copy out operation in this case to avoid potential side effects but this makes code generation a bit more complex for the method body -- even in the second case, I don't see why an exception is needed, this can be done with a simple flag, and even by a static analysis at compile time in most cases).
"out" parameter: here the compiler must check that all execution paths assign a value to the "out" parameter inside the method body (unless they throw an exception of course), the same way it checks that all execution paths return a value if the method has a non void return type. Here, if the method returns "normally", it must assign a value to "out" parameter.
Consider:
public bool GetNamedThing(string name, inout Thing thing)
{
if (ThingTable.Contains(name))
{
thing = ThingTable.GetThing(name);
return true;
}
else
{
return false;
}
}
//at th ecall point
if (GetNamedThing("thingy", inout this.MyThing))
{
//do stuff
}
now, if you don't want MyThing to be changed on the return of the value of
false, there is no simple way to express that. You would *have* to throw an
exception or the value is copied anyway. Basically the same way ref works
now but with the same resultant effect as pass by name would have in this
case.
Introducing rules that try to measure the return value would be very bad as
well, IMHO. You'd have to have a special form of return if you wanted to
return boolean failures. Bruno.
> Consider: public bool GetNamedThing(string name, inout Thing thing) { if (ThingTable.Contains(name)) { thing = ThingTable.GetThing(name); return true; } else { return false; } }
//at th ecall point
if (GetNamedThing("thingy", inout this.MyThing)) { //do stuff }
now, if you don't want MyThing to be changed on the return of the value of false, there is no simple way to express that. You would *have* to throw
an exception or the value is copied anyway. Basically the same way ref works now but with the same resultant effect as pass by name would have in this case.
If the return is false, this.MyThing will be reassigned the value that it
had on entry. This is no big deal as long as there is no side effect
involved and no strong perf penalty involved.
As I explained in my post, it is possible for the compiler to generate a
slightly "smarter" IL that will avoid the copy-out assignment if the method
did not reassign the thing argument. What we see here is only the surface,
and behind the scenes, the compiler may very well generate its IL as if the
method had the following signature:
bool GetNamedThingBody(string name, ref Thing thing, ref bool
thingAssigned)
And generate code that sets thingAssigned to true in the path that leads to
"return true", and generate code that tests thingAssigned before performing
the copyout assignment.
I am not sure that this additional subtlety is not really worth the trouble
and the basic version (copyout reassigns the original value) may be
sufficient. Then, if you really want to avoid the potential side effect of
reassigning the same value, you can still pass a variable and assign it to
the property after the call (reproducing what you are doing today with ref).
In any case, all this can be achieved without introducing an exception. I
don't understand why you absolutely want this to be handled via an EH
mechanism.
Introducing rules that try to measure the return value would be very bad
as well, IMHO. You'd have to have a special form of return if you wanted to return boolean failures.
The rule that I am proposing to avoid the reassignment of the same value
does not measure the return value, it measures the presence of an assignment
of the inout parameter in the execution path. This is very different.
I don't understand why we would need a "special form or return" for boolean
failures. Can you explain?
Also, copyin/copyout is not an invention of my own, it is used by some well
known languages, ADA for example. I 'm not saying that ADA should be our
guideline, but sometimes, looking at other languages can give interesting
ideas.
Bruno.
>> Introducing rules that try to measure the return value would be very bad as well, IMHO. You'd have to have a special form of return if you wanted to return boolean failures. The rule that I am proposing to avoid the reassignment of the same value does not measure the return value, it measures the presence of an assignment of the inout parameter in the execution path. This is very different. I don't understand why we would need a "special form or return" for boolean failures. Can you explain?
The problem is that only an exception allows you to escape the method
without copyout. Basically it requires modifying the way you write the
method with the inout parameter so that the value isn't assigned until every
error condition is satisfied. It creates a fun little difference in returns
and exceptions. Its more of an issue with the patterns involved with passing
a property(or a field) to a value vs passing a local. Code patterns have to
change somewhere. This proposal moves that into the, probably better,
location of the method itself, but it leaves you without an escape outside
of exceptions. Also, copyin/copyout is not an invention of my own, it is used by some well known languages, ADA for example. I 'm not saying that ADA should be our guideline, but sometimes, looking at other languages can give interesting ideas.
I agree, I made a similar suggestion that ref\out could have been extended
to get\set properties using such a mechanism not long ago(my basic idea then
had indeed been having the compiler generate a temp local which it passes as
ref and copies back to the property). However I made that suggestion to
support *not* using fields in ref parameters.
As I always suggest, implemting and playing with the feature would help
illustrate the issues more than simple conjecture, from MVP's or otherwise,
;). Bruno.
Daniel O'Connell [C# MVP] <onyxkirx@--NOSPAM--comcast.net> wrote: The problem is that only an exception allows you to escape the method without copyout. Basically it requires modifying the way you write the method with the inout parameter so that the value isn't assigned until every error condition is satisfied. It creates a fun little difference in returns and exceptions. Its more of an issue with the patterns involved with passing a property(or a field) to a value vs passing a local. Code patterns have to change somewhere. This proposal moves that into the, probably better, location of the method itself, but it leaves you without an escape outside of exceptions.
I'm not sure I see the problem - what's the difference here between out
and copyout? The only one I can see is that on successful return, the
output parameter's value is assigned to the actual property/variable
parameter. If an exception is thrown, any temporary value of the output
parameter is ignored, and if the actual parameter is a variable, it's
not deemed as assigned (just as is the case with out parameters now).
--
Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om... Daniel O'Connell [C# MVP] <onyxkirx@--NOSPAM--comcast.net> wrote: The problem is that only an exception allows you to escape the method without copyout. Basically it requires modifying the way you write the method with the inout parameter so that the value isn't assigned until every error condition is satisfied. It creates a fun little difference in returns and exceptions. Its more of an issue with the patterns involved with passing a property(or a field) to a value vs passing a local. Code patterns have to change somewhere. This proposal moves that into the, probably better, location of the method itself, but it leaves you without an escape outside of exceptions. I'm not sure I see the problem - what's the difference here between out and copyout? The only one I can see is that on successful return, the output parameter's value is assigned to the actual property/variable parameter. If an exception is thrown, any temporary value of the output parameter is ignored, and if the actual parameter is a variable, it's not deemed as assigned (just as is the case with out parameters now).
Only that copyout would let you write to properties. I'd have no argument
against inout without access to properties, but when you allow it to modify
state, I do have issue with the exact semantics and the inability to leave a
method without an exception AND without copyout is a problem, IMHO.
Basically there is successful return or exceptions, nothign else. Just not
assigning the variable could be a problem. If the user expects an assignment
to a property and it never comes that would introduce potential bugs and
make code more confusing. I am simply not convinced that throwing exceptions
is enough flexibility. -- Jon Skeet - <sk***@pobox.com> http://www.pobox.com/~skeet If replying to the group, please do not mail me too This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Ville Vainio |
last post by:
I don't know if you have seen this before, but here goes:
http://text.userlinux.com/white_paper.html
There is a jab at Python, though, mentioning that Ruby is more
"refined".
--
Ville...
|
by: C# Learner |
last post by:
Note
----
Please use a fixed-width font to view this, such as Courier New.
Problem
|
by: Charles Arthur |
last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
|
by: emmanuelkatto |
last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud.
Please let me know.
Thanks!
Emmanuel
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
|
by: Sonnysonu |
last post by:
This is the data of csv file
1 2 3
1 2 3
1 2 3
1 2 3
2 3
2 3
3
the lengths should be different i have to store the data by column-wise with in the specific length.
suppose the i have to...
|
by: Hystou |
last post by:
There are some requirements for setting up RAID:
1. The motherboard and BIOS support RAID configuration.
2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
|
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers,...
|
by: jinu1996 |
last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
|
by: agi2029 |
last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
| |