pass by reference without the ref keyword - c#

I'm not a veteran in socket programming, so while analyzing code I found in a database API I came across this code
public static void WriteInt(int i, NetworkStream bufOutputStream)
{
byte[] buffer = new byte[IntSize];
WriteInt(i, buffer, 0);
bufOutputStream.Write(buffer, 0, buffer.Length);
}
public static void WriteInt(int i, byte[] byte_array, int pos)
{
byte_array[pos] =(byte)( 0xff & (i >> 24)); byte_array[pos+1] = (byte)(0xff & (i >> 16)); byte_array[pos+2] = (byte)(0xff & (i >> 8)); byte_array[pos+3] = (byte)(0xff & i);
}
I understand the bit-shifts what I don't understand is how the 'buffer' var keeps getting a value when no ref is in the args or no return is made. the bitshifts are somehow editing the actual value of buffer?

Your confusion is a very common one. The essential point is realising that "reference types" and "passing by refrence" (ref keyboard) are totally independent. In this specific case, since byte[] is a reference type (as are all arrays), it means the object is not copied when you pass it around, hence you are always referring to the same object.
I strongly recommend that you read Jon Skeet's excellent article on Parameter passing in C#, and all should become clear...

Because an array isn't a value type, it's a reference type. The reference to the location on the heap is passed by value.

I think some examples can show you differences between reference types and value types and between passing by reference and passing by value:
//Reference type
class Foo {
public int I { get; set; }
}
//Value type
struct Boo {
//I know, that mutable structures are evil, but it only an example
public int I { get; set; }
}
class Program
{
//Passing reference type by value
//We can change reference object (Foo::I can changed),
//but not reference itself (f must be the same reference
//to the same object)
static void ClassByValue1(Foo f) {
//
f.I++;
}
//Passing reference type by value
//Here I try to change reference itself,
//but it doesn't work!
static void ClassByValue2(Foo f) {
//But we can't change the reference itself
f = new Foo { I = f.I + 1 };
}
//Passing reference typ by reference
//Here we can change Foo object
//and reference itself (f may reference to another object)
static void ClassByReference(ref Foo f) {
f = new Foo { I = -1 };
}
//Passing value type by value
//We can't change Boo object
static void StructByValue(Boo b) {
b.I++;
}
//Passing value tye by reference
//We can change Boo object
static void StructByReference(ref Boo b) {
b.I++;
}
static void Main(string[] args)
{
Foo f = new Foo { I = 1 };
//Reference object passed by value.
//We can change reference object itself, but we can't change reference
ClassByValue1(f);
Debug.Assert(f.I == 2);
ClassByValue2(f);
//"f" still referenced to the same object!
Debug.Assert(f.I == 2);
ClassByReference(ref f);
//Now "f" referenced to newly created object.
//Passing by references allow change referenced itself,
//not only referenced object
Debug.Assert(f.I == -1);
Boo b = new Boo { I = 1 };
StructByValue(b);
//Value type passes by value "b" can't changed!
Debug.Assert(b.I == 1);
StructByReference(ref b);
//Value type passed by referenced.
//We can change value type object!
Debug.Assert(b.I == 2);
Console.ReadKey();
}
}

The best way to think about this is to think about the variables. Variables are by definition storage locations. What are the storage locations in your program? They are:
the formal parameters i and bufOutputStream of the first WriteInt.
the local variable buffer in the first WriteInt
the elements ("IntSize" of them) of the array referred to by buffer, after it is allocated.
the formal parameters i, byte_array and pos of the second WriteInt
The byte_array storage location and the buffer storage location are different storage locations. But the byte_array storage location contains a reference to the same array that the buffer storage location refers to. Therefore buffer[0] and byte_array[0] refer to the same storage location.
Just think about the storage locations, and it'll all make sense.

C# is like Java in that reference type variables are actually pointers. You always pass by value, but with reference types the value is the location of the object, rather than the object itself. The ref keyword on a reference type is passing the pointer by reference, so an assignment to a ref parameter will change what object the argument passed in points to.

Arrays in .Net are reference types.
Therefore, your function receives a reference to the array object by value. Since there is still only a single array instance, the function can modify the instance and the changes will be seen the caller.
Adding the ref keyword would make the function receive a reference to the array object by reference, and would therefore allow the function to change the reference to refer to a different array instance.
In other words, the ref keyword would allow you to write the following:
public static void WriteInt(int i, ref byte[] byte_array, int pos)
{
byte_array = new byte[0]; //In the caller, the array will now be empty.
}
To demonstrate:
void SetReference(ref byte[] arrayRef) { arrayRef = new byte[1]; }
void SetValue(byte[] arrayVal) { arrayVal[1] = 42; }
byte[] array = new byte[4];
byte[] sameArray = array; //sameArray refers to the same instance
sameArray[0] = 77; //Since it's the same instance, array[4] is also 77.
SetValue(array); //array[1] is 42.
//Since it refers to the same array, sameArray[1] is also 42.
SetReference(ref array); //sameArray now refers to a new array of length 1.
//array still refers to the original array.

byte_array is a reference type.

Like Yuriy Faktorovich said, value types (like int, char, bool ecc.) are passed by default by value (unless you specify ref)
all other types (arrays, and Objects) are passed by default by reference
in your example if u change the values inside the array it will reflect changes also outside the method but you cannot reassign the object.
a full reference about it is in MSDN

Related

Do I need to reset a stream(C#) back to the start if I pass stream into method as Pass Value-Type Parameter method

I have seen a couple of the example on internet stated that I have to reset the stream by
stream.Seek(0, SeekOrigin.Begin);
However, if I pass the stream into a method as
public static bool ValidateStreamLine(Stream stream)
Do I have to still reset the stream?
Understand that on usual case if I pass in int, string, float or any other general variable type as
public static bool ValidateInt(int i)
the value of int i would not change.
Would that be any difference of the nature of Pass-by Value method on how the method react to stream?
You seem to be misunderstanding how arguments are passed in C#. By default, all arguments are passed by value in C#. In order to pass them by reference you need to use a special keyword: ref or out the latter being normally used when the argument is used as a second output of a given method. (See int.TryPase for example).
The important thing to understand here is that arguments passed by value behave quite diferently if the type of the argument is a reference type or a value type. This is where you seem to be confused.
To understand how it all works, make sure you are clear on the following:
Variables hold values.
The value of a variable whose type is a value type, is the value type's instance itself:
int i = 1 // i holds the value 1
The value of a variable whose type is a reference type is not the instance of said type. The value is the memory address where that instance lives.
string s = "Hello!" // s does not hold "Hello!" it holds a number that points to a place in memory where the string "Hello!" lives.
So, now that we are clear on that, what happens when you pass arguments by value (C#'s default)? What happens is that a copy of the variable is made and the copy is passed to the method.
If the type is a reference type, what is really copied and passed to the method is the value stored in the variable. And what is that? The memory address where the object referenced by the variable lives. So you see what happens? Both the original variable and the copied variable both point to the same object:
public class Foo
{
var frobbed = false;
public bool Frobbed { get { return frobbed; } }
public void Frob() { frobbed = true; }
}
void Frob(Foo foo) { foo.Frob(); }
var myFoo = new Foo();
Frob(myFoo);
Console.WriteLine(myFoo.Frobbed); //Outputs True! Why? Because myFoo and foo both point to the same object! The value of both variables (memory address) is the same!
If the type is a value type, the value itself of the value type is copied and handed to the method so there is no way the method can modify the value type stored in the original variable.
public void Increment(int i) { i = i + 1; }
var myInt = 1;
Increment(myInt);
Console.WriteLine(myInt); //Outputs 1, not 2. Why? i holds its own copy of 1, it knows nothing about the copy of 1 stored in myInt.
Things change when you pass arguments by reference. Now, the argument passed to the method is not a copy, its the original variable itself. A logical question follows; does this actually change anything in how reference types behave? The answer is yes, quite a lot:
public void ByValueCall(string s)
{
s = "Goodbye";
}
public void ByReferenceCall(ref string s)
{
s = "Goodbye";
}
var myString = "Hello!";
Console.WriteLine(ByValueCall(myString )); //outputs "Hello!"
Console.WriteLine(ByValueCall(myString )); //outputs "Goodbye!"
This behavior is identical with value types too. What is happening here?
When you pass an argument by value, the method gets a copy of the variable; therefore assigning a new value to the argument is really just assigning a new value to the copy; the original variable at the callsite doesn't care that you change the value of it's copy, be it a value type or a reference type. It will keep holding the value it always had.
When passing an argument by reference, you are not passing a copy, you are passing the variable itself. In that case assigning a new value to the variable will persist at the callsite. A canonical example is the following swap method:
public void Swap(ref int a, ref int b)
{
var temp = a;
a = b;
b = temp;
}
var i1 = 1;
var i2 = 2;
Swap(ref i1, ref i2);
var b = i1 == 2; //true
b = i2 == 1; //true
So after all of this, you should understand why the following behaves the way it does:
public ResetStream(Stream stream)
{
stream.Seek(0, SeekOrigin.Begin);
}
var myStream = new ...
myStream.Read(bytes, 0, 1024);
ResetStream(myStream);
var isAtOrigin = myStream.Position == 0; //Returns true!

Difference between Reference Types and References

I am reading following blog by Eric Lippert: The truth about Value types
In this, he mentions there are 3 kinds of values in the opening:
Instance of Value types
Instance of Reference types
References
It is incomplete. What about references? References are neither value types nor instances of reference types, but they are values..
So, in the following example:
int i = 10;
string s = "Hello"
First is instance of value type and second is instance of reference type. So, what is the third type, References and how do we obtain that?
So, what is the third type, References and how do we obtain that?
The variable s is a variable which holds the value of the reference. This value is a reference to a string (with a value of "Hello") in memory.
To make this more clear, say you have:
string s1 = "Hello";
string s2 = s1;
In this case, s1 and s2 are both variables that are each a reference to the same reference type instance (the string). There is only a single actual string instance (the reference type) involved here, but there are two references to that instance.
Fields and variables of reference type, such as your s, are references to an instance of a reference type that lives on the heap.
You never use an instance of a reference type directly; instead, you use it through a reference.
A reference is not really a 'third type'. It's actually a pointer that refers to a concrete instance of an object. Take a look at this example:
class MyClass
{
public string Str { get; set; }
}
class Program
{
static void Main(string[] args)
{
int a = 1;
int b = 2;
int c = 3;
var myObj = new MyClass
{
Str = "Whatever"
};
Console.WriteLine("{0};\t{1};\t{2};\t{3}", a, b, c, myObj.Str);
MyFunction(a, ref b, out c, myObj);
Console.WriteLine("{0};\t{1};\t{2};\t{3}", a, b, c, myObj.Str);
Console.ReadLine();
}
static void MyFunction(int justValue, ref int refInt, out int outInt, MyClass obj)
{
obj.Str = "Hello";
justValue = 101;
refInt = 102;
outInt = 103; // similar to refInt, but you MUST set the value of the parameter if it's uses 'out' keyword
}
}
The output of this program is:
1; 2; 3; Whatever
1; 102; 103; Hello
Focus on the MyFunction:
The first parameter we pass is a simple int which is a value type. By default value types are cloned when passed as the parameter (a new instance is being created). That's why the value of 'a' didn't change.
You can change this behavior by adding 'ref' or 'out' keyword to the parameter. In this case you actually pass a reference to that very instance of your int. In MyFunction the value of that instance is being overridden.
Here you can read move out ref and out
The last example is the object of MyClass. All classes are reference types and that's why you always pass them as references (no special keywords needed).
You can think about a reference as about an address in computer memory. Bytes at that address compose your object. If you pass it as value, you take that bytes out and pass them to a function. If you pass it as a reference you only pass the address. Than in your called function you can read bytes from that address or write to that address. Every change affects the calling function variables, because they point to exactly the same bytes in computer memory. It's not exactly what happens in .Net (it runs in a virtual machine), but I think this analogy will help you understand the concept.
Why do we use references? There are many reasons. One of them is that passing a big object by value would be very slow and would require cloning it. When you pass a reference to an object, than no matter how big that object is you only pass w few bytes that contain it's 'address' in memory.
Moreover your object may contain elements that cannot be cloned (like an open socket). Using reference you can easily pass such an object between functions.
It's also worth mentioning that sctructs, even though they look very similar to classes are actually value types and behave as value types (when you pass a struct to a function, you actually pass a clone - a new instance).

Why is Interfaces behaviour different when using value types and reference types

I did the following example in c#
interface IChangeable
{
void Change(params Int32[] array);
}
struct SomeValueType : IChangeable
{
private Int32 m_X;
public SomeValueType(int X)
{
m_X = X;
}
public void Change(params Int32[] array)
{
m_X = array[0];
}
public override string ToString()
{
return String.Format("Crt value of m_X: {0}", m_X);
}
}
And in Main:
static void Main(String[] args)
{
SomeValueType someValueType = new SomeValueType(5);
Console.WriteLine(someValueType); // No boxing occured. It showed: 5
Object someRefType = someValueType; // Boxed
Console.WriteLine(someRefType); // Also Shows 5 (from heap)
someValueType.Change(2); // Change Value of x not o's
Console.WriteLine(someValueType + " " + someRefType); // 2 5
((SomeValueType)someRefType).Change(3); // Copies to a temp stack so no change ocuured in o
Console.WriteLine(someRefType); // 5
IChangeable itfStackChange = (IChangeable)someValueType;
itfStackChange.Change(7);
Console.WriteLine(someValueType); // Shows 2 and not 7 ... why?
IChangeable itfChange = (IChangeable)someRefType;
itfChange.Change(1); // Unboxes the value of o, making the value of x 1 boxes o again?
Console.WriteLine(someRefType); // Shows 1
}
Now I am wondering what happens when I do:
IChangeable itfStackChange = (IChangeable)someValueType; //value was 2 and its still 2
itfStackChange.Change(7);
Console.WriteLine(someValueType);
But if I change the definition of struct to class like in:
class SomeValueType : IChangeable
It writes 7 and not 2.
Value types semantics are such that the value gets copied on assignment. This means that when you change after assignment, the variables point to different objects.
For reference types the reference gets copied, meaning that when you change after assignment, both variables point to the same object.
See Value Types and Reference Types on MSDN.
A structure-type definition actually defines two kinds of things: a kind of storage location, and a kind of heap object which inherits from the abstract class System.ValueType. The heap object effectively has one field of the corresponding storage-location type, but exposes all the members of that storage-location type as though they were its own. To the outside world, the heap type will behave like a class object; internally, however, references to this are references to its field of the corresponding storage-location type.
Although C# defines the term "inheritance" in such a way as to pretend that the storage-location type and the heap-object type are one and the same, the two types will behave differently. Casting a value type to an interface that it represents will generate a new heap object which holds a copy of the public and private fields of the value type that was cast, and then return a reference to that new instance. The resulting reference will exhibit reference semantics, since it will be a reference.
If one regards heap objects and value-type storage locations as existing in separate universes, and recognizes the cases in which values must be copied from one universe to the other, one will find that such a model will accurately predict how things will behave.

In C#, is it the same as in Java refering to object creation during methods?

I have a programming competition tomorrow and I have a quick question:
In Java, if you would pass an object in a parameter for a method, you actually got not a copy of the object, but the actual object.
Is it the same as C#?
public static void PunchyManager(string[] inputArray, ref int a, ref int b)
{
string[] tempStrArray = inputArray;
}
If I do that will I basically make a pointer to inputArray, instead of having a copy?
Just a quick question, thanks!
In regard to your basic question in relation to Java Yes.
More generally Yes and no. Reference types (classes) are passed by reference which is like a single pointer. For something that can truly modify references outside the caller you should use the ref keyword even on reference types. This is similiar to a double pointer (assuming we are referring to pointers as they work in C for our pointer analogies).
class RefRefExample
{
static void Method(ref string s)
{
s = "changed";
}
static void Main()
{
string str = "original";
Method(ref str);
// str is now "changed"
}
}
In the above example if we passed str without using the ref keyword we would reassign the local reference of s instead of the original reference of str. By passing our reference by reference we can modify the original reference outside of the function as well. References themselves are still copied by value (but the copied reference still points to the same value) without the ref keyword.
http://msdn.microsoft.com/en-us/library/14akc2c7(v=vs.80).aspx
For practical usage in the scenario you are describing the modern C# idiom usually uses lists and they will likely be much faster to use as far as programming in your competition:
public static void PunchyManager(List<string> inputList, ref int a, ref int b)
{
var tempList = new List<string>();
foreach (var item in inputList)
tempList.Add(item);
}
Working on the original input list would modify objects through the reference so you would be affecting the original values outside of the method whereas the templList is a copy - Lists are very convenient.
Furthermore you can convert them back to Arrays using .ToArray()
*edit Oh, you wish to know if it is the same in c# as java, your wording was a bit off.
Correct, if you do
public static void main(String[] args)
{
int myArray[] = new int[1];
test(myArray);
System.out.println(myArray[0]);
}
public void test(int[] array)
{
array[0] = 1;
}
You will get an output of 1
In CLR there are two kinds of objects:
Reference types (also known as just "objects")
Value types (also known as "structures" or "structs", even they are technically objects too).
The difference between them is that "objects" are located on heap, when "structs" are located on stack.
Types like Int32, Int64, Float, Double, etc are value types (structs). You can also define your own structure:
public struct MyStruct { ... }
Therefore, when you pass a "struct" around it is passed by copying the value.
Example:
int x = 5; //creates a value type on stack
int y = x; //makes a copy so now we have two objects on stack, not just one
"Objects" are passed by reference.
object x = new Object(); //create an object, x holds a reference to this object
object y = x; // y now holds a reference to the same object x has a reference to.
When you pass reference types around you generally don't need to use a ref keyword. However, if you want to pass a reference to a value type instance you may want to use this keyword.
Yes, class instances are passed as references in C#. If you want to pass value type (like Int32) as reference you need to use ref keyword.
Thing is, If you pass the parameter with keyword ref, modification of the variable inside the method will be reflected to caller as well. This is applicable to even struct(exmple int). But for struct or class, if you pass the parameter with out ref/out, this will be assumed as pass by value, which means, modification inside the method cannot be reflected to caller for structs. For classes, modification will be reflected to caller still without passing with out ref. BUT, StringBuilder sb = new StringBuilder() statement ask the sb to point to this one (an newly created new StringBuilder()). So reference knot will be moved from one which was pointed in the caller to new StringBuilder() in the callee. This has to be remembered always.
Pass by value with ref:
static void Main(string[] args)
{
StringBuilder y = new StringBuilder();
y.Append("hello");
Foo(ref y);
Console.WriteLine(y);
}
private static void Foo(ref StringBuilder y)
{
StringBuilder sb = y;
sb.Append("99");
}
o/p : hello99
Pass by value without ref:
static void Main(string[] args)
{
StringBuilder y = new StringBuilder();
y.Append("hello");
Foo(y);
Console.WriteLine(y);
}
private static void Foo(StringBuilder y)
{
StringBuilder sb = new StringBuilder
sb.Append("99");
}
o/p : hello
To assign something different to your array you'd want to have the parameter use the 'ref' keyword.
http://msdn.microsoft.com/en-us/library/szasx730(v=vs.71).aspx

What is the use of "ref" for reference-type variables in C#?

I understand that if I pass a value-type (int, struct, etc.) as a parameter (without the ref keyword), a copy of that variable is passed to the method, but if I use the ref keyword a reference to that variable is passed, not a new one.
But with reference-types, like classes, even without the ref keyword, a reference is passed to the method, not a copy. So what is the use of the ref keyword with reference-types?
Take for example:
var x = new Foo();
What is the difference between the following?
void Bar(Foo y) {
y.Name = "2";
}
and
void Bar(ref Foo y) {
y.Name = "2";
}
You can change what foo points to using y:
Foo foo = new Foo("1");
void Bar(ref Foo y)
{
y = new Foo("2");
}
Bar(ref foo);
// foo.Name == "2"
There are cases where you want to modify the actual reference and not the object pointed to:
void Swap<T>(ref T x, ref T y) {
T t = x;
x = y;
y = t;
}
var test = new[] { "0", "1" };
Swap(ref test[0], ref test[1]);
Jon Skeet wrote a great article about parameter passing in C#. It details clearly the exact behaviour and usage of passing parameters by value, by reference (ref), and by output (out).
Here's an important quote from that page in relation to ref parameters:
Reference parameters don't pass the
values of the variables used in the
function member invocation - they use
the variables themselves. Rather than
creating a new storage location for
the variable in the function member
declaration, the same storage location
is used, so the value of the variable
in the function member and the value
of the reference parameter will always
be the same. Reference parameters need
the ref modifier as part of both the
declaration and the invocation - that
means it's always clear when you're
passing something by reference.
Very nicely explained here :
http://msdn.microsoft.com/en-us/library/s6938f28.aspx
Abstract from the article:
A variable of a reference type does not contain its data directly; it
contains a reference to its data. When you pass a reference-type
parameter by value, it is possible to change the data pointed to by
the reference, such as the value of a class member. However, you
cannot change the value of the reference itself; that is, you cannot
use the same reference to allocate memory for a new class and have it
persist outside the block. To do that, pass the parameter using the
ref or out keyword.
When you pass a reference type with the ref keyword, you pass the reference by reference, and the method you call can assign a new value to the parameter. That change will propagate to the calling scope. Without ref, the reference is passed by value, and this doesn't happen.
C# also has the 'out' keyword which is a lot like ref, except that with 'ref', arguments must be initialized before calling the method, and with 'out' you must assign a value in the receiving method.
It allows you to modify the reference passed in. e.g.
void Bar()
{
var y = new Foo();
Baz(ref y);
}
void Baz(ref Foo y)
{
y.Name = "2";
// Overwrite the reference
y = new Foo();
}
You can also use out if you don't care about the reference passed in:
void Bar()
{
var y = new Foo();
Baz(out y);
}
void Baz(out Foo y)
{
// Return a new reference
y = new Foo();
}
Another bunch of code
class O
{
public int prop = 0;
}
class Program
{
static void Main(string[] args)
{
O o1 = new O();
o1.prop = 1;
O o2 = new O();
o2.prop = 2;
o1modifier(o1);
o2modifier(ref o2);
Console.WriteLine("1 : " + o1.prop.ToString());
Console.WriteLine("2 : " + o2.prop.ToString());
Console.ReadLine();
}
static void o1modifier(O o)
{
o = new O();
o.prop = 3;
}
static void o2modifier(ref O o)
{
o = new O();
o.prop = 4;
}
}
In addition to the existing answers:
As you asked for the difference of the 2 methods: There is no co(ntra)variance when using ref or out:
class Foo { }
class FooBar : Foo { }
static void Bar(Foo foo) { }
static void Bar(ref Foo foo) { foo = new Foo(); }
void Main()
{
Foo foo = null;
Bar(foo); // OK
Bar(ref foo); // OK
FooBar fooBar = null;
Bar(fooBar); // OK (covariance)
Bar(ref fooBar); // compile time error
}
A parameter in a method seems to be always passing a copy, the question is a copy of what. A copy is done by a copy constructor for an object and since all variables are Object in C#, i believe this is the case for all of them. Variables(objects) are like people living at some addresses. We either change the people living at those addresses or we can create more references to the people living at those addresses in the phone book(make shallow copies). So, more than one identifier can refer to the same address. Reference types desire more space, so unlike value types that are directly connected by an arrow to their identifier in the stack, they have value for another address in the heap( a bigger space to dwell). This space needs to be taken from the heap.
Value type:
Indentifier(contains value =address of stack value)---->Value of value type
Reference type:
Identifier(contains value=address of stack value)---->(contains value=address of heap value)---->Heap value(most often contains addresses to other values), imagine more arrows sticking in different directions to Array[0], Array[1], array[2]
The only way to change a value is to follow the arrows. If one arrow gets lost/changed in the way the value is unreachable.
Reference Variables carry the address from one place to another so any updation on them at any place will reflect on all the places THEN what is the use of REF.
Reference variable (405) are good till no new memory is allocated to the reference variable passed in the method.
Once new memory allocate (410) then the value change on this object (408) will not reflect everywhere.
For this ref comes. Ref is reference of reference so whenever new memory allocate it get to know because it is pointing to that location therefore the value can be shared by everyOne. You can see the image for more clearity.

Categories

Resources