Just trying to see if someone can help me understand this:
What is the difference in usage between these two examples below? When is the second, passing an argument by reference better? Both output the same result.
public static void Sqr(int x)
{
x = x * x;
Console.WriteLine(x);
}
static void Main(string[] args)
{
Sqr(3);
}
2)
public static void Sqr(ref int x)
{
x = x * x;
}
static void Main(string[] args)
{
int a = 3;
Sqr(ref a);
Console.WriteLine(a);
}
Anyone know? I’m clueless here. My problem is that don’t really even know why things are written the way they are!! Any insights?
Both output the same result.
That's because as well as changing whether or not it's a ref parameter, you've changed where you've got the output.
Here's a version of your first piece of code that is closer to the second, so they only differ in whether or not it's a ref parameter:
public static void Sqr(int x)
{
x = x * x;
}
static void Main(string[] args)
{
int a = 3;
Sqr(a);
Console.WriteLine(a);
}
Now the output will be 3, because the value of a hasn't changed - its value was passed to the Sqr method. In your second example, the variable itself is passed by reference, so x in the Sqr method and a in the Main method refer to the same storage location... the change to the value of x can be "seen" via a after the method has returned.
When is the second, passing an argument by reference better?
When you want changes in the parameter to be reflected in the argument. That's relatively rare, and I'd encourage you to use value parameters by default. For example, it would be more idiomatic to write Sqr as:
public static int Sqr(int x)
{
return x * x;
}
Then call it as:
a = Sqr(a);
ref parameters are relatively rarely useful in my experience - but it's important to understand how they work. (You may find my article on parameter passing useful for more details.)
Related
I have a function that repeatedly calls another function.
The second function has a bool parameter that changes the way it behaves, so when I call the first function I want to have a parameter that specifies the way the second function behaves.
void Function1(int n, bool differentBehavior = false)
{
int a = Function2(n, differentBehavior);
int b = Function2(1, differentBehavior);
int c = Function2(2, differentBehavior);
return a + b + c;
}
int Function2(int x, bool differentBehavior)
{
if (!differentBehavior) // do something
else // do something else
}
The code itself is obviously an example (in reality the second function is called over 20 times and for code readability I would love to not have to specify the second parameter every time), but I put it there to explain what I'm currently doing. Is there no better way to achieve this?
You can introduce a local function to capture the second argument like so:
int Function1(int n, bool differentBehavior = false)
{
int func(int n) => Function2(n, differentBehavior);
int a = func(n);
int b = func(1);
int c = func(2);
return a + b + c;
}
This is called "partial function application". See more here:
https://codeblog.jonskeet.uk/2012/01/30/currying-vs-partial-function-application/
While C# doesn't support true function Currying nor first-class partial function application, you can always
use a new locally scoped function (aka a local function) to wrap your Function2 with predefined arguments... which is conceptually almost the same thing as partial application, just without referential-transparency, and awkward delegate types.
Anyway, if you want to pass the outer Function1's differentBehavior argument value to Function2 then you will need to use a closure, which will capture the variable, but this will introduce slight runtime performance complications: as a closure generally means a GC heap allocation and copying function local state from the stack onto the heap and yada yada.
However, if you're only using constant parameter values - or you're okay with using different wrappers for different predefined argument values, then you can use a static local function (requires C# 8.0 or later) which prevents you from unintentionally creating a closure.
For example:
void Function1(int n, bool differentBehavior = false)
{
// Look ma, no closure!
static int PartiallyAppliedFunc2_False(int x) => Function2( x: x, differentBehavior: false );
static int PartiallyAppliedFunc2_True(int x) => Function2( x: x, differentBehavior: true );
int a = PartiallyAppliedFunc2_False(n);
int b = PartiallyAppliedFunc2_False(1);
int c = PartiallyAppliedFunc2_True(2);
return a + b + c;
}
int Function2(int x, bool differentBehavior)
{
if (!differentBehavior) // do something
else // do something else
}
One thing to look at when a lot of parameters are being passed on the stack is whether there is some higher-level state that could be represented by a member variable of the class.
Here's some code for the most basic kind of state machine. This general approach might help solve the problem you're having:
class Program
{
enum Behaviors
{
BehaviorA,
BehaviorB,
BehaviorC,
}
static Behaviors State { get; set; }
static void Main(string[] args)
{
for (State = Behaviors.BehaviorA; State <= Behaviors.BehaviorC; State++)
{
Console.WriteLine($"Function returned { Function1(0)}");
}
int Function1(int n)
{
int a = Function2(n);
int b = Function2(1);
int c = Function2(2);
return a + b + c;
}
int Function2(int x)
{
switch (State)
{
case Behaviors.BehaviorA:
return x * 10;
case Behaviors.BehaviorB:
return x * 20;
case Behaviors.BehaviorC:
return x * 30;
default:
throw new NotImplementedException();
}
}
}
}
Want feedback if i`m correct here?
Use void if you are not returning anything in a method,
otherwise
Name your data types used in the method criteria before method name.
use Return in the method before the calculation or output.
So something like this.
static int MyMethod(int x)
{
return 5 + x;
}
static void Main(string[] args)
{
Console.WriteLine(MyMethod(3));
}
// Outputs 8 (5 + 3)
What if my method has ints and doubles?
Do I write as follows? (another words do I have to mention every type i`m using prior to the method name?
static int double myMethod (int x, double y)
Even with that I dont know when is a method void? It seems my methods all return values.
Isnt the following returning the values of the arguments? So why should I label it void?
static void MyMethod(string fname, int age)
{
Console.WriteLine(fname + " is " + age);
}
static void Main(string[] args)
{
MyMethod("Liam", 20);
MyMethod("Jenny", 25);
MyMethod("Tom", 31);
}
I can only think that a void means there is no new calculation being done in the actual method body, passing arguments into a method and spitting them out for user viewing does not mean its "returning a value", I dont know what i`m talking about.
Let's be completely clear about what these bullets mean.
Use void if you are not returning anything in a method, otherwise
In this context, "return" means that the method provides an output that can be assigned to a variable by the caller. For example
int Return10()
{
return 10;
}
...allows the caller to do this:
int x = Return10();
Console.WriteLine(x); //Outputs "10"
A method should "return" void when its results cannot be assigned. For example, if the results are printed on the screen.
void Print10()
{
Console.WriteLine("10"); //Prints 10 to the screen
}
...which allows the caller to do this:
Print10();
You cannot assign it because it doesn't return anything. This doesn't work:
int x = Print10(); //Compiler error
Name your data types used in the method criteria before method name.
A method can return exactly one value or object. So "types" here is wrong. You can only specify one type.
Use return in the method before the calculation or output.
This is a little misleading. The return keyword should be followed by an expression which can be assigned.
int Return10()
{
return 10 + 10; //Is okay because it's an expression and could be assigned
}
int Return10()
{
var x = 10 + 10;
return x; //This is also okay; in fact it does exactly the same thing as the previous example
}
int Return10()
{
return Console.WriteLine("10"); //Compiler error; can't be assigned to anything.
}
By the way, a method can also output something and return it:
int WriteAndReturn10()
{
int x = 10;
Console.WriteLine(x);
return x;
}
I am going to address the following
What if my method has ints and doubles? Do I write as follows?
(another words do I have to mention every type i`m using prior to the
method name?
There are no built in ways or syntax to return more than one type from a method as the return parameter.. This is basically historical and has been this way since dinosaurs roamed the earth.
However, there are lots of options that achieve the same result. For instance, you could use a custom struct, you could use out parameters, you could use a class, or a delegate parameter of some kind. However, a modern succinct approach might be to use a Value Tuple:
static (int someInt, double someDouble) myMethod (int x, double y)
{
return (x,y);
}
Fun Fact : even though this looks like you a returning more than one type, you are actually just invoking a special syntax that wraps your return parameters in a single type of struct
Usage
var result = myMethod(1,2.2);
Console.WriteLine(result.someInt);
Console.WriteLine(result.someDouble);
Or if you want to get fancy, you can use the newer deconstructed syntax
var (someInt, someDouble) = myMethod(1,2.2);
Console.WriteLine(someInt);
Console.WriteLine(someDouble);
Additional Resources
return (C# Reference)
Methods (C# Programming Guide)
Tuple types (C# reference)
out parameter modifier (C# Reference)
ref (C# Reference)
Using Delegates (C# Programming Guide)
I want to ask something about ref modifier.
What I know and understand:
With method that use ref modifier, there will be no copy of data as with passing by value, but parameter will have directly access to argument value. Basically said, all you done in method’s scope will act same as if you would done it with argument (passed variable) in caller’s scope.
and I want to ask what is exactly stored in parameter with ref modifier:
When I pass argument to method with ref modifier, will parameter contain reference to value of argument? or is it something else?
Thank you for your answers
When you have a parameter with the ref attribute, it passes the argument by reference and not value. That means a new copy of the variable is not being made, rather a pointer to the original is being used within your function.
public void Foo()
{
var x = 0;
Bar(x); // x still equals 0
Bar(ref x); // x now equals 1
}
public void Bar(ref int x)
{
x = 1;
}
public void Bar(int x)
{
x = 1;
}
Let's say we have this method:
public void DoSomething(int number)
{
number = 20;
}
And we use it:
var number = 10;
DoSomething(number);
Console.WriteLine("Our number is: {0}", number);
The output would be Our number is: 10. Our number does not become 20.
That's because we're passing by value, so we're basically taking a copy of number before we change it.
However, if we pass by reference instead:
public void DoSomething(ref int number)
{
number = 20;
}
And then use our method:
var number = 10;
DoSomething(ref number);
Console.WriteLine("Our number is: {0}", number);
The output then becomes Our number is: 20
Would anyone be so kind to post the equivalent Java code for a closure like this one (obtained using C#) with anonymous inner classes?
public static Func<int, int> IncrementByN()
{
int n = 0; // n is local to the method
Func<int, int> increment = delegate(int x)
{
n++;
return x + n;
};
return increment;
}
static void Main(string[] args)
{
var v = IncrementByN();
Console.WriteLine(v(5)); // output 6
Console.WriteLine(v(6)); // output 8
}
Furthermore, can anyone explain how partial applications can be obtained if lexical closures are available and viceversa? For this second question, C# would be appreciated but it's your choice.
Thanks so much.
There is no closure yet in Java. Lambda expressions are coming in java 8. However, the only issue with what you're trying to translate is that it has state, which not something that lamba expressions will support i don't think. Keep in mind, it's really just a shorthand so that you can easily implement single method interfaces. You can however still simulate this I believe:
final AtomicInteger n = new AtomicInteger(0);
IncrementByN v = (int x) -> x + n.incrementAndGet();
System.out.println(v.increment(5));
System.out.println(v.increment(6));
I have not tested this code though, it's just meant as an example of what might possibly work in java 8.
Think of the collections api. Let's say they have this interface:
public interface CollectionMapper<S,T> {
public T map(S source);
}
And a method on java.util.Collection:
public interface Collection<K> {
public <T> Collection<T> map(CollectionMapper<K,T> mapper);
}
Now, let's see that without closures:
Collection<Long> mapped = coll.map(new CollectionMapper<Foo,Long>() {
public Long map(Foo foo) {
return foo.getLong();
}
}
Why not just write this:
Collection<Long> mapped = ...;
for (Foo foo : coll) {
mapped.add(foo.getLong());
}
Much more concise right?
Now introduce lambdas:
Collection<Long> mapped = coll.map( (Foo foo) -> foo.getLong() );
See how much nicer the syntax is? And you can chain it too (we'll assume there's an interface to do filtering which which returns boolean values to determine whether to filter out a value or not):
Collection<Long> mappedAndFiltered =
coll.map( (Foo foo) -> foo.getLong() )
.filter( (Long val) -> val.longValue() < 1000L );
This code is equivalent I believe (at least it produces the desired output):
public class Test {
static interface IncrementByN {
int increment(int x);
}
public static void main(String[] args) throws InterruptedException {
IncrementByN v = new IncrementByN() { //anonymous class
int n = 0;
#Override
public int increment(int x) {
n++;
return x + n;
}
};
System.out.println(v.increment(5)); // output 6
System.out.println(v.increment(6)); // output 8
}
}
Assuming we have a generic function interface:
public interface Func<A, B> {
B call A();
}
Then we can write it like this:
public class IncrementByN {
public static Func<Integer, Integer> IncrementByN()
{
final int n_outer = 0; // n is local to the method
Func<Integer, Integer> increment = new Func<Integer, Integer>() {
int n = n_outer; // capture it into a non-final instance variable
// we can really just write int n = 0; here
public Integer call(Integer x) {
n++;
return x + n;
}
};
return increment;
}
public static void main(String[] args) {
Func<Integer, Integer> v = IncrementByN();
System.out.println(v.call(5)); // output 6
System.out.println(v.call(6)); // output 8
}
}
Some notes:
In your program, you capture the variable n by reference from the enclosing scope, and can modify that variable from the closure. In Java, you can only capture final variables (thus capture is only by value).
What I did here is capture the final variable from the outside, and then assign it into a non-final instance variable inside the anonymous class. This allows "passing info" into the closure and at the same time having it be assignable inside the closure. However, this information flow only works "one way" -- changes to n inside the closure is not reflected in the enclosing scope. This is appropriate for this example because that local variable in the method is not used again after being captured by the closure.
If, instead, you want to be able to pass information "both ways", i.e. have the closure also be able to change things in the enclosing scope, and vice versa, you will need to instead capture a mutable data structure, like an array, and then make changes to elements inside that. That is uglier, and is rarer to need to do.
This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
Why use ref keyword when passing an Object?
When to pass ref keyword in
What is the correct usage of the 'ref' keyword in C#. I believe there has been plenty of discussion threads on this, but what is not clear to me is:
Is the ref keyword required if you are passing in a reference object? I mean when you create an object in the heap, is it not always passed by reference. Does this have to be explicitly marked as a ref?
Using ref means that the reference is passed to the function.
The default behaviour is that the function receives a new reference to the same object. This means if you change the value of the reference (e.g. set it to a new object) then you are no longer pointing to the original, source object. When you pass using ref then changing the value of the reference changes the source reference - because they are the same thing.
Consider this:
public class Thing
{
public string Property {get;set;}
}
public static void Go(Thing thing)
{
thing = new Thing();
thing.Property = "Changed";
}
public static void Go(ref Thing thing)
{
thing = new Thing();
thing.Property = "Changed";
}
Then if you run
var g = new Thing();
// this will not alter g
Go(g);
// this *will* alter g
Go(ref g);
There is a lot of confusing misinformation in the answers here. The easiest way to understand this is to abandon the idea that "ref" means "by reference". A better way to think about it is that "ref" means "I want this formal parameter on the callee side to be an alias for a particular variable on the caller side".
When you say
void M(ref int y) { y = 123; }
...
int x = 456;
M(ref x);
that is saying "during the call to M, the formal parameter y on the callee side is another name for the variable x on the caller side". Assigning 123 to y is exactly the same as assigning 123 to x because they are the same variable, a variable with two names.
That's all. Don't think about reference types or value types or whatever, don't think about passing by reference or passing by value. All "ref" means is "temporarily make a second name for this variable".
I believe the ref keyword indicates that you are passing the object by reference, not by value. For example:
void myfunction(ref object a) {
a = new Something();
}
would change the value of a in the calling function
However,
void myfunction(object a) {
a = new Something();
}
would change the value of a locally, but not in the calling function. You can still change PROPERTIES of the item, but you cannot set the value of the item itself. For example;
a.someproperty = value;
would work in both cases.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace InOutRef
{
static class InOutRef
{
public static void In(int i)
{
Console.WriteLine(i);
i=100;
Console.WriteLine(i);
}
public static void Ref(ref int i)
{
Console.WriteLine(i);
i=200;
Console.WriteLine(i);
}
public static void Out(out int i)
{
//Console.WriteLine(i); //Error Unsigned Ref
i=300;
Console.WriteLine(i);
}
}
class Program
{
static void Main(string[] args)
{
int i = 1;
InOutRef.In(i); //passed by value (in only)
Debug.Assert(i==1);
InOutRef.Ref(ref i); //passed by ref (in or out)
Debug.Assert(i == 200);
InOutRef.Out(out i); //passed by as out ref (out only)
Debug.Assert(i == 300);
}
}
}
I can't be any more literal on my answer. The code will not remember reference chanages such as the classic Java swap question when using in. However, when using ref, it will be similar to VB.NET as it will remember the changes in and out. If you use the out parameter it means that it must be declared before you return (this is enforced by the compiler).
Output:
1 //1 from main
100 //100 from in
1 //1 is NOT remembered from In
200 //200 from ref
//should be 200 here but out enforces out param (not printed because commented out)
300 //300 is out only
Press any key to continue . . .