I have the below piece of code which Prefixs a string to the start of each member of a string array. ie. ["a","b","c"] prefixed with "z" becomes ["za","zb","zc"].
private string[] Prefix(string[] a, string b) {
for(int i = 0;i < a.Length;i++) {
a[i] = b + a[i];
}
return a;
}
The function works fine (although if theres a better way to do this, I'm happy to hear it), but I'm having issues when passing parameters.
string[] s1 = new string[] {"a","b"};
string[] s2 = Prefix(s1,"z");
Now as far as I can tell, I'm passing s1 by Value. But when the Prefix function has finished, s2 and s1 have the same value of ["za,"zb"], or s1 has been passed by reference. I was certain you had to explicitly declare this behaviour in c#, and am very confused.
As others have said, the reference is passed by value. That means your s1 reference is copied to a, but they both still refer to the same object in memory. What I would to do fix your code is write it like this:
private IEnumerable<string> Prefix(IEnumerable<string> a, string b) {
return a.Select(s => b + s);
}
.
string[] s1 = new string[] {"a","b"};
string[] s2 = Prefix(s1,"z").ToArray();
This not only fixes your problem, but also allows you to work with Lists and other string collections in addition to simple arrays.
C#, like Java before it, passes everything by value by default.
However, for reference types, that value is a reference. Note that both string and array are reference types.
Here's a better way to do it:
private string[] Prefix(string[] a, string b) {
return a.Select(s => b + s).ToArray();
}
or even:
private IEnumerable<string> Prefix(IEnumerable<string> a, string b) {
return a.Select(s => b + s);
}
You are passing the reference to s1 by value. In other words, your a parameter (when in the Prefix function scope), and your s1 variable, are references to the same array.
strings are immutable
this means that when you append a string to a string you get out a totally new string - its for performance reasons. its cheaper to make a new string that to reallocate the existing array.
hence why it feels like you are working with strings by value
in c# all reference types are passed by reference by default - ie classes creaped on the heap rather than values.
Actually, a reference to s1 was passed by value to Prefix(). While you now have two different references, both s1 and s2 still refer to the same string array, as arrays are reference types in C#.
Passing by value doesn't mean that you can't change things.
Objects are passed by value, but the value is (effectively) a pointer to the object.
Arrays are objects and a pointer to the array gets passed in. If you change the contents of the array in a method, the array will reflect the changes.
This doesn't happen with strings only because strings are immutable - once constructed, their contents can't change.
A reference to the string array is passed by value.
Consequently, the original array reference in the calling method cannot be changed, meaning that a = new string[10] within the Prefix method would have no impact on the s1 reference in the calling method. But the array itself is mutable, and a duplicate reference to the same array is capable of making changes to it in a way that would be visible to any other reference to the same array.
The value of an object is passed. For "reference" objects this is the value of the reference. A clone/copy/duplicate of the underlying data is not made.
To fix the issue observed, simply don't mutate the input array -- instead, create a new output array/object and fill it in appropriately. (If you must use arrays, I would likely use this approach as it's so boringly C-like anyway.)
Alternately, you can clone the input array first (which also creates a new object). Using a clone (which is a shallow copy) in this case is okay because the inner members (strings) are themselves immutable -- even though they are reference types the value of the underlying object can't be changed once created. For nested mutable types, more care may need to be taken.
Here are two methods which can be used to create a shallow copy:
string[] B = (string[])A.Clone();
string[] B = (new List<string>(A)).ToArray();
It's not inclusive.
Personally though, I would use LINQ. Here is a teaser:
return a.Select(x => b + x).ToArray();
Related
I have a class named ACTIVITY. This class contains a list of Laps, and each Lap has a collection of TRACPOINTS.
ACTIVITY --many--> LAPS ---many --> TRACPOINTS.
Whenever I fLatten the TRACPOINTS collection I get the list of all the TRACPOINTS. But when I modify those of course the originals don't get modified since it's a copy.
Is there any way that whatever change I made to the flattened tracpoints gets changed in the Tracpoints list for each lap?
As long as TRACPOINT is a struct, it is not possible in any reasonable way.
Whenever you assign a value of struct variable or field to another variable or field, its contents are copied. The same holds for passing it as a method argument or returning it from a method, its value is copied. This is value semantics [1]. Compare this to atomic types like int, which have value semantics too. You would probably expect the following code to print 2, not 3.
static function Change(int j) { j = 3; }
static void Main(string[] args) {
int i = 2;
Change(i);
System.Console.WriteLine(i);
}
If you do SelectMany, each value from the collection is probably assigned to some temporary local variable and then returned from the iterator (SelectMany), therefore it is copied and in fact possibly copied many times before it comes out from the iterator. So what you are updating is a copy of the struct. Like in the example, you're not changing variable i, but its copy stored in variable j.
This is why structs should be immutable. Instead of having properties with getters and setter in your struct, they should have only getters. For changing values of properties of a struct, you can implement methods that copy the whole original struct, change the value of the desired property and return the new struct instance. In fact, again, its copy will be returned. Example:
struct S {
int f;
public int F { get { return this.f; } }
public S SetF(int newVal) {
var s = new S();
s.f = newVal;
return s;
}
}
var x = new S();
x = x.SetF(30);
That said, it could be possible to achieve what you want with pointers and unsafe C#, but believe me, it will be way easier to change your structs to classes, so that they have reference semantics instead of value semantics, or keep them structs, but make them immutable and do not use Linq, but old school loops. If you want to use Linq for something like SelectMany in such scenario, you probably do not care about performance difference between structs and classes so much...
[1] http://msdn.microsoft.com/en-us/library/aa664472(v=vs.71).aspx
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).
In C#, string is a reference type. Then,
Why do I need to have my swap function to have ref parameters?
swap(ref string first, ref string second) //swap(string first, string second) doesn't work
{
temp = first;
first = second
second = temp;
}
You are confusing two different kinds of references. Strings are references to instances. Your swap function takes references to variables.
Think about it this way. You have two books, "A Christmas Carol" and "Pickwick Papers". They're books; they've got pages and text and whatnot.
You have ten pieces of paper. Five says "A Christmas Carol". Five says "Pickwick Papers". The papers are references to the books. They're not the books.
You have ten drawers labelled A, B, C, D, E, F, G, H, I, J. You put the papers that says "A Christmas Carol" into drawer A through E, and the papers that says "Pickwick Papers" into drawers F through J.
Now you want to swap the contents of drawers E and I. What information do you have to give to the swapper? You can't tell the swapper "Swap references to Christmas Carol for Pickwick Papers", because that would change all ten drawers, not just E and I. The information you have to give to the swapper is "E" and "I". You have to pass reference to two variables; the fact that the variables themselves contain a reference to a book is irrelevant.
Your swapper has three drawers of its own, labelled first, second and temp. It takes two piece of paper. One says "E", and that goes in the drawer labelled "first". One says "I" and that goes in the drawer labelled "second".
The swapper looks in "first" and finds a paper that says "E". It looks in "E" and finds a paper that says "Christmas Carol". It makes a photocopy of that paper and puts the copy in "temp"... and you see how this goes from here I hope.
Yes, string is a reference type and this
void swap(string first, string second)
passes references to the string objects to the function.
But string is immutable so it is not possible for the swap function to change the objects through these references. For strings, the only way to implement a swap function is to use the ref keyword to pass the references by reference so the references can be swapped.
OTOH, if you have a mutable class, you can write a swap function without using the ref keyword:
class Foo
{
public int Bar { get; set; }
}
static void Swap(Foo first, Foo second)
{
var temp = first.Bar;
first.Bar = second.Bar;
second.Bar = temp;
}
Foo foo1 = new Foo { Bar = 1 };
Foo foo1Copy = foo1;
Foo foo2 = new Foo { Bar = 2 };
Swap(foo1, foo2);
But note, that after the swap, foo1Copy.Bar == 2, since the object referenced by foo1 and foo1Copy was modified.
Because parameters in C# by default are passed by value, not reference. Adding ref gives you pass-by-reference behavior.
The reference to the string is passed by value. There's a big difference between passing a reference by value and passing an object by reference. It's unfortunate that the word "reference" is used in both cases.
If you pass an object into a method, you are passing the actual object and not the address in memory of the object. You could not then assign a new value to it as you would be changing what object is stored in a memory address elsewhere, not the original.
By adding the ref keyword, you pass the objects by reference. This means you essentially give the method access to the address where the objects are stored, so when you swap the objects, the original memory addresses will then refer to the swapped object.
String is a reference type. It is passed by value to the method by default. If you actually want to change the value of the string, you need to pass it by reference. The below msdn article explains it in detail.
http://msdn.microsoft.com/en-us/library/s6938f28(v=vs.80).aspx
Inside main i declared a local int[] array (int[] nums). I did not pass it by reference.
But when i print values of local array i get squared value of each element.
What is the reason for that?
delegate void tsquare(int[] a);
static void Main()
{
int[] nums = { 1, 2, 3 };
tsquare sqr = new tsquare(SomeClass.Square);
sqr(nums);
foreach (int intvals in nums)
{
Console.WriteLine(intvals);
}
}
class SomeClass
{
public static void Square(int[] array)
{
for (int i = 0; i < array.Length; i++)
{
array[i] = array[i] * array[i];
}
}
}
Update:
My appologies to all.What i tought is int[] {Array}is a value type,and the Delegate done
some trick on it.Now from your answer ,i understand Array is Reference type.
There are two concepts here.
Reference types vs. value types
Passing by value vs. passing by reference
Let's tackle the second one first.
Passing something by value means that you give the method its own copy of that value, and it's free to change that value however it wants to, without those changes leaking back into the code that called the method.
For instance, this:
Int32 x = 10;
SomeMethod(x); // pass by value
There's no way x is going to be anything other than 10 after the call returns in this case, since whatever SomeMethod did to its copy of the value, it only did to its own value.
However, passing by reference means that we don't really give the method its own value to play with, rather we give it the location in memory where our own value is located, and thus anything that method does to the value will be reflected back to our code, because in reality, there's only one value in play.
So this:
Int32 x = 10;
SomeMethod(ref x); // pass by reference
In this case, x might hold a different value after SomeMethod returns than it did before it was called.
So that's passing by value vs. passing by reference.
And now to muddle the waters. There's another concept, reference types vs. value types, which many confuses. Your question alludes to you being confused about the issue as well, my apologies if you're not.
A reference type is actually a two-part thing. It's a reference, and it's whatever the reference refers to. Think of a house you know the address of. You writing the address on a piece of paper does not actually put the entire house on that paper, rather you have a "reference" to that particular house on your piece of paper.
A reference type in .NET is the same thing. Somewhere in memory there is an object, which is a set of values, grouped together. The address of this object you store in a variable. This variable is declared to be a type which is a reference type, which allows this two-part deal.
The nice thing about reference types is that you might have many references to the same actual object, so even if you copy the reference around, you still only have one object in memory.
Edit: In respect to the question, an array is a reference type. This means that your variable only holds the address of the actual array, and that array object is located somewhere else in memory.
A value type, however, is one thing, the entire value is part of the "value type", and when you make copies of that, you make distinct copies
Here's an example of value types:
struct SomeType
{
public Int32 Value;
}
SomeType x = new SomeType;
x.Value = 10;
SomeType y = x; // value type, so y is now a copy of x
y.Value = 20; // x.Value is still 10
However, with a reference type, you're not making a copy of the object it refers to, only the reference to it. Think of it like copying the address of that house onto a second piece of paper. You still only have one house.
So, by simply changing the type of SomeType to be a reference type (changing struct to class):
class SomeType
{
public Int32 Value;
}
SomeType x = new SomeType;
x.Value = 10;
SomeType y = x; // reference type, so y now refers to the same object x refers to
y.Value = 20; // now x.Value is also 20, since x and y refer to the same object
And now for the final thing; passing a reference type by value.
Take this method:
public void Test(SomeType t)
{
t.Value = 25;
}
Given our class-version of SomeType above, what we have here is a method that takes a reference type parameter, but it takes it as being passed by value.
What that means is that Test cannot change t to refer to another object altogether, and make that change leak back into the calling code. Think of this as calling a friend, and giving him the address you have on your piece of paper. No matter what your friend is doing to that house, the address you have on your paper won't change.
But, that method is free to modify the contents of the object being referred to. In that house/friend scenario, your friend is free to go and visit that house, and rearrange the furniture. Since there is only one house in play, if you go to that house after he has rearranged it, you'll see his changes.
If you change the method to pass the reference type by reference, not only is that method free to rearrange the contents of the object being referred to, but the method is also free to replace the object with an altogether new object, and have that change reflect back into the calling code. Basically, your friend can tell you back "From now on, use this new address I'll read to you instead of the old one, and forget the old one altogether".
The array reference is passed by value automatically because it is a reference type.
Read:
Reference Types
Value Types
Most of the other answers are correct but I believe the terminology is confusing and warrants explanation. By default, you can say that all parameters in C# are passed by value, meaning the contents of the variable are copied to the method variable. This is intuitive with variables of value types, but the trick is in remembering that variables that are reference types (including arrays) are actually pointers. The memory location the pointer contains is copied to the method when it is passed in.
When you apply the ref modifier, the method gets the actual variable from the caller. For the most part the behavior is the same, but consider the following:
public void DoesNothing(int[] nums)
{
nums = new []{1, 2, 3, 4};
}
In DoesNothing, we instantiate a new int array and assign it to nums. When the method exits, the assignment is not seen by the caller, because the method was manipulating a copy of the reference (pointer) that was passed in.
public void DoesSomething(ref int[] nums)
{
nums = new []{1, 2, 3, 4};
}
With the ref keyword, the method can essentially reach out and affect the original variable itself from the caller.
To achieve what you seemed to originally want, you could create a new array and return it, or use Array.CopyTo() in the caller.
In C#, all parameters are passed by value by default. There are two kinds of types in C#, namely value and reference types.
A variable of reference type when passed as a parameter to a function will still be passed by value; that is if the function changes the object referred to by that variable, after the function completes the variable that was passed in will still refer to the same object (including null) as it did prior to calling the function in the same context.
However, if you use the ref modifier when declaring the function parameter than the function may change the object being referenced by the variable in the caller's context.
For Value types this is more straightforward but it is the same concept. Bear in mind, int[] is a reference type (as are all arrays).
Consider the differences in these functions when passing in some some array of ints:
public static void Square1(int[] array)
{
for (int i = 0; i < array.Length; i++)
{
array[i] = array[i] * array[i];
}
}
public static void Square2(int[] array)
{
array = {10, 20, 30};
for (int i = 0; i < array.Length; i++)
{
array[i] = array[i] * array[i];
}
}
public static void Square3(ref int[] array)
{
array = {10, 20, 30};
for (int i = 0; i < array.Length; i++)
{
array[i] = array[i] * array[i];
}
}
You're not passing it by reference. The array is being passed in by value, but arrays in .NET are reference types, so you're passing in a reference to the array, which is why you're seeing the values squared.
Read the following SO question - it explains the differences between pass-by-value and pass-by-reference. The accepted answer has a link in it to a good article about the topic that should help you understand the difference.
what is different between Passing by value and Passing by reference using C#
Arrays are objects and are passed by reference. Ints are structs and are passed by value (unless you use the ref keyword in your method signature as per the picky guy in the comments) (who was right) (but picky).
I have one doubt in string .
How can we acess the memory of string?
is String is reference type or Value type?
1) if it is Reference type then do the following code
List<String> strLst = new List<string>() { "abc","def","12"};
strLst.ForEach(delegate(string s)
{
if (s == "12")
{
s = "wser";
// I doubted whether = operator is overloaded in string class
//StringBuilder sb = new StringBuilder(s);
//s = sb.Append("eiru").ToString();
s = String.Concat(s, "sdf");
}
});
See that value of string is not changed. My question is why the string value is not changed?
If it is reference type then the string value should be changed.
class emp
{
public string id;
}
List<emp> e = new List<emp>() { new emp() { id = "sdf" }, new emp() { id = "1" }, new emp() { id = "2" } };
e.ForEach(delegate(emp em)
{
if (em.id == "1")
em.id = "fghe";
});
Here value is changed because emp is reference type
2) if string is value type
public sealed class String : IComparable, ICloneable, IConvertible, IComparable<string>, IEnumerable<char>, IEnumerable, IEquatable<string>
then why do they mentione that string is a class?
This is happening because of this part:
s = "wser";
This is exactly equivalent to:
s = new String ("wser");
When you write this, a new object is instantiated and its reference is stored in s. Thus, the previous reference is completely lost in the function scope and no change is noticed outside the scope.
Thus, to notice changes in a reference type changed in another scope, you cannot create a new instance and assign it to the variable name, you must modify the original reference itself (and this is not possible for a string object in Java - strings are immutable).
The System.String type is indeed a reference type, albeit a rather strange one. It is immutable from a developer's perspective, and the CLR treats it pretty much like a value type, so you won't go far wrong doing the same.
Jon Skeet's article on parameter passing, value types, and reference types in C#, also gives a good explanation of this curiosity:
Note that many types (such as string)
appear in some ways to be value types,
but in fact are reference types. These
are known as immutable types. This
means that once an instance has been
constructed, it can't be changed. This
allows a reference type to act
similarly to a value type in some ways
- in particular, if you hold a reference to an immutable object, you
can feel comfortable in returning it
from a method or passing it to another
method, safe in the knowledge that it
won't be changed behind your back.
This is why, for instance, the
string.Replace doesn't change the
string it is called on, but returns a
new instance with the new string data
in - if the original string were
changed, any other variables holding a
reference to the string would see the
change, which is very rarely what is
desired.
If you store the reference to an object in a variable and then change the reference, the object does not change, only the variable. You're changing a propert of em, thus affecting the object references by the variable em. If you instead did em = something, it would behave like the String example and not affect anything either.
The String type is a reference type, but it is immutable. This means you can't change the contents of the string.
It actually behaves like a value type, but only references are passed around, instead of the whole string object.
From the MSDN online page - string
Strings are immutable--the contents of a string object cannot be changed. Although string is a reference type, the equality operators (== and !=) are defined to compare the values of string objects, not references.
Why can't strings be mutable in Java and .NET?
String is a reference type.
The reason why the string in the list is not changing in your example, is that the method doesn't get access to the item in the list, it only gets a copy of the reference. The argument s is just a local variable in the method, so assigning a new value to it doesn't affect the contents of the list.