|
-
October 12th, 2012, 02:16 PM
#10
Re: Pointers - Unsafe
OK, suppose you have this:
Code:
public static void Test(int val)
{
val = -val;
}
public static void Test(string val)
{
val = val.ToLower(); // ToLower() returns a new string, all in lowercase
}
public static void Test(Element val)
{
// mutate
val.Value = "The Old New Thing";
// replace
val = new Element();
val.Value = "New!";
}
What will the value of the original object be when the methods return? To answer that question, you must understand the distinction which C# makes between value types (structs) and reference types (classes). All the fundamental types (byte, int, long, float, double, bool...), except for string, are value types. They are passed around by value by default. String type is a reference type, but is specific in that it's, by design, immutable. That is, when you assign a new string to a variable, it's not the contents of the string objects that changes, but the whole object itself gets replaced. (This enables the language to share same string literals among string variables.) Now, for the code above, all of the variables are local copies, so replacing them will not have any effect on the original. So, the integer will not change, the original string will not be replaced, and the Element object (a reference type) will not be replaced, but it will be mutated (changed internally), and it's Value property will be "The Old New Thing".
It's like when you pass a pointer to an object in C++: a local copy of the pointer is made, but it still points to the same object, so you can modify that object.
Code:
Originals:
n: 5
s: STRING!
e: OLD
No ref keyword:
n: 5
s: STRING!
e: The Old New Thing
Now, in C#, the ref keyword is a part of the signature, so you can overload all those methods, like this:
Code:
public static void Test(ref int val)
{
val = -val;
}
public static void Test(ref string val)
{
val = val.ToLower();
}
public static void Test(ref Element val)
{
// mutate
val.Value = "The Old New Thing";
// replace
val = new Element();
val.Value = "New!";
}
What happens now?
For value types, it's straightforward - the ref keyword forces them to be passed by reference. For reference types, the reference itself is passed by reference - analogous to a C++ pointer being passed by reference. This means that you can now make it point to an entirely different object. So, after each of the methods returns, the original integer will be changed, the original string variable will point to a new string, and the original element variable will point to a new object, with the Value property set to "New!".
Code:
Originals
n: 5
s: STRING
e: OLD
Using ref
n: -5
s: string
e: New!
You can try calling these methods in a console application, in the Main() method, and see for yourself. Something like this:
Code:
int n = 5;
string s = "STRING!";
Element e = new Element(); // This is just some class (the one I used in your other thread, the linked list example)
e.Value = "OLD"; // all it does is it stores a string value
Console.WriteLine("Originals:");
PrintValues(n, s, e);
Test(n);
Test(s);
Test(e);
Console.WriteLine("No ref keyword:");
PrintValues(n, s, e);
Test(ref n);
Test(ref s);
Test(ref e);
Console.WriteLine("Using ref keyword:");
PrintValues(n, s, e);
PrintValues() is just a helper method:
Code:
private static void PrintValues(int n, string s, Element e)
{
Console.WriteLine("n: {0}", n);
Console.WriteLine("s: {0}", s);
Console.WriteLine("e: {0}", e.Value);
Console.WriteLine();
}
P.S. In the IDE, you can discover if a type is a value type or a reference type by hovering a mouse over a type name and looking if it says struct or class. You can also rely on the MSDN documentation.
Last edited by TheGreatCthulhu; October 12th, 2012 at 02:20 PM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|