Reputation: 2193
What is the difference between
private void DoSomething(int value) {
value++;
}
and
private int DoSomething(int value) {
return value++;
}
when used as either
DoSomething(value);
versus
value = DoSomething(value);
Upvotes: 38
Views: 79052
Reputation: 19825
Return a value.
Why?
Correctness, Readability, and Self-Documentation
Intentional and easy to understand code is better than side-effect code. Consider:
float area = pi * Square(r);
vs.
Square(r);
float area = pi * r;
// ... intervening code
float x = r * 5; // did you mean to use the original r or r-squared here?
Also consider the advantages of terseness through composability in the first example.
Consider the methods themselves, compare:
int DoSomething(int value)
{ return value+1; }
Which is pretty obviously correct. vs.
void DoSomething(int value)
{ value++; }
Which seems right and will compile just fine but is actually just a no-op. What you really want is this:
void DoSomething(ref int value)
{ value++; }
// client code:
DoSomething(ref a);
Variables are Cheap
Many well-named variables is preferable over few reused general purpose variables. Resist the temptation to prematurely optimize, the chance that you will need to cut down on the number of local variables to improve the performance of your system is cosmically tiny. Again, Variables are Cheap, DON'T REUSE VARIABLES!
Testability
Consider:
Assert.IsTrue(Square(2) == 4);
vs.
float a = 2;
Square(a);
Assert.IsTrue(a == 4);
There are many other advantages to avoiding mutation in preference to returning a value. It's not merely an accident that mathematics defines a function as a mapping of input values to output values.
Upvotes: 41
Reputation: 144122
You are talking about the difference between passing by reference and passing by value, which is conceptually similar to the idea of value types vs reference types.
If you pass a value type into the method, you have to use the second example; otherwise you are just incrementing an integer that exists inside the scope of DoSomething(). Try it: if you execute your first example, after DoSomething() has run, the value of your int will be unchanged.
However, if you are passing in something other than a value type (say object foo), you are actually passing a reference to the original object. Anything you do to it inside DoSomething() will take effect outside the method as well, since you are still referring to the same object.
You can accomplish what you're attempting in the first example by writing:
void DoSomething(ref int value)
That instructs .NET to pass a reference to the item regardless of whether it is a value type.
See this writeup on Value Types vs Reference Types on MSDN for a more detailed look.
Additionally, as zodoz points out (upvote appropriately), by returning value++
you are returning and then incrementing. To return the incremented value, use ++value
.
Upvotes: 75
Reputation: 3257
Everyone else seems to be suggesting the difference in variable passing, but I noticed something different:
If the example code you are displaying is a simplification of something you are already looking at, then you might want to note that in your second example:
private int DoSomething(int value) {
return value++;
}
The value
will return then increment. So if you do the following:
public Main() {
int val = 1;
Console.writeln(DoSomething(val));
}
Your output will be 1
.
Let me know if this helps at all.
Upvotes: 6
Reputation: 827496
In your first example, the int parameter value
is incremented, but is destroyed when the method ends, you cannot get the value outside the method, unless you use the ref or out keywords.
For example:
private int DoSomething(ref int value) {
return value++;
}
// ...
int myValue = 5;
DoSomething(ref myValue);
// Now myValue is 6.
Ref and out parameter passing modes are used to allow a method to alter variables passed in by the method caller. The main difference between ref and out may be subtle but it's important.
Each parameter passing mode is designed to suite different programming needs.
The caller of a method which takes an out parameter is not required to assign to the variable passed as the out parameter prior to the call; however, the method is required to assign to the out parameter before returning.
One way to think of out parameters is that they are like additional return values of a method. They are convenient when a method should return more than one value.
The ref parameters causes the arguments to be passed by reference. The effect is that any changes to the parameter in the method will be reflected in that variable when control passes back to the calling method.
Do not confuse the concept of passing by reference with the concept of reference types.
The two concepts are not related; a method parameter can be modified by ref regardless of whether it is a value type or a reference type, there is no boxing of a value type when it is passed by reference.
Upvotes: 1
Reputation: 46585
Simply the first one won't work because you're operating on a copy of value.
You could do something like
private int DoSomething(ref int value)
{
value++;
}
and call it like
DoSomething(ref value);
This changes value to be passed in by reference. But really the only reason to do this is if you want to return more than one thing from your function. And normally there are better ways.
For extra bonus knowledge, there's also the out keyword which is similar to ref, but doesn't require value to be initialised first.
Upvotes: 4