Click to See Complete Forum and Search --> : function's parameters


underwar
March 9th, 2003, 05:20 PM
When we pass string to a function - does C# create copy of the original string or it sends refrence to the original one?
As I know, it sends refrence to the original string - but if so - why we need the 'ref' keyword?

MartinL
March 10th, 2003, 03:18 AM
If you specify the string parameter as ref, it will refer to the same variable as was passed into the function. If you don't specify it, it will refer to the same varibale unless you assign new string into that parameter...

Thats why we need the ref and out keywords.

martin

bfarley
March 10th, 2003, 09:45 AM
"As I know, it sends refrence to the original string"
Errr... no. Value objects are passed by value. If a string is passed in without a ref keyword, you are only changing a copy - will not change original string.

Bill F

MartinL
March 10th, 2003, 09:47 AM
string is a class. And all classes in .NET are reference types...

bfarley
March 10th, 2003, 10:26 AM
OK, it may be a reference type - but it is not passed by ref. Consider:

using System;

public class console
{
public static int Main(string[] args)
{
string strToMod="TEST";
Join(strToMod);
Console.WriteLine(strToMod);
Console.ReadLine();
return 0;
}
static void Join(string strToMod)
{
strToMod = strToMod+" - modified";
Console.WriteLine(strToMod);
}
}

If paseed by ref, both ConsoleWriteLines should produce "TEST - modified". But the one that follows the Join() call prints "TEST". It is not modified.

Bill F

MartinL
March 10th, 2003, 10:47 AM
Read the answer I posted again...


If you don't specify it, it will refer to the same varibale unless you assign new string into that parameter...


You assign new string into that variable...

Consider this C++ code:

void ManipStr(char* str)
{
str = (char*)malloc(100);
strcpy(str, "manipstr1");
}

void ManipStr2(char** str)
{
*str = (char*)malloc(100);
strcpy(*str, "manipstr2");
}

int main(int argc, char* argv[])
{
char* str = (char*)malloc(100);
strcpy(str, "string");

printf("Befor ManipStr call: %s\n", str);

ManipStr(str);
printf("After ManipStr call: %s\n", str);

ManipStr2(&str);
printf("After ManipStr2 call: %s\n", str);

free(str);

getch();

return 0;
}


Yes, it has a memory leek however it demonstrate the diference between "normal" call and "ref" call in C#...

Normal call is like in ManipStr function. Just pointer is passed there, however if you assign new string into it the variable you passed there is not changed...

However, ManipStr2 is "equivalent" for ref keyword using in C#...

Martin

pareshgh
March 10th, 2003, 11:32 AM
Bill,
objects are passed as,
1) reference with ref keyword
2) copy - as simple in your program

if you use ref then only it will modify.
else its not possible.


Paresh

MartinL
March 10th, 2003, 11:48 AM
Paresh I have to disagree!

Look at this code:

using System;

namespace SomeApplication
{
class Cls
{
protected string str = null;

public Cls()
{
str = "Initial object state";
}

public string Str
{
get { return str; }
set { str = value; }
}
}

class Class1
{
[STAThread]
static void Main(string[] args)
{
Class1 app = new Class1();
app.Run();
}

public Class1()
{
}

void Run()
{
Cls obj = new Cls();
Console.WriteLine(obj.Str);
Func(obj);
Console.WriteLine(obj.Str);
Console.ReadLine();
}

void Func(Cls cls)
{
cls.Str = "object has been modified";
}
}
}

The output of this app is following:

Initial object state
object has been modified

It means that all classes are passed by the reference... However you have to explicitelly specified ref if you want to assign new value to the parementer inside of the function...

Martin

pareshgh
March 10th, 2003, 11:58 AM
No,


// here you make an object
Cls obj = new Cls();

// just the public member print Console.WriteLine(obj.Str);

// you are actually passing the object
// where this function actually takes the object and
// modifies the public member that's what it does
Func(obj);

// actually when cls is created locally here its still alive and u modify its member so it has to change since its alive already.
// again following is the printing
Console.WriteLine(obj.Str);
Console.ReadLine();


Note : if this is the case why not just with passing the string only. since object is created in memory and you are modifiing it.

BTW: ref will modify to the actuall object passed and it will reffer to the same object. for example
myfunc(ref string str)
{
str = "original changed contents";
}

str1="foo";
by calling
myfunc(ref str1);
it actually referes to the same str1 which was created and which gets modified in myfunc.

in your example 'cls ' object is alive within boundary of main .. so .. it has to change the member ... its nothing new ...

Paresh

MartinL
March 10th, 2003, 12:35 PM
Hm Paresh...

What did you want to say by those comments... I can translate it into main language however, I don't understand them... :D :D :D

--> Cls obj = new Cls();

Yes, I made an object there... In the same way as when I wrote:

String str = "this is a string";

Forget about not using the new keyword in the line above. You can use it!!!!

--> Func(obj)

Yes, I actually pass an object into the function. Exactely the same as when I wrote:

string str = new string('x', 10);
FuncWithStringParameter(str);

It is exactelly the same!!!

--> // actually when cls is created locally here its still alive and u
--> modify its member so it has to change since its alive already.

Sorry, I really don't know what you mean by this sentence...:confused:

It doesn't depend on where I create the object (cls or string... ), Cls is created by the new operator and while the program has reference to it (it is visible in the domain), the object is alive. I can create it in some function and return it. Or I can make that variable class member and create it in constructor...

--> Note : if this is the case why not just with passing the string
--> only. since object is created in memory and you are modifiing it.

String class is written in a little different way. I can't ilustrate this behavior on the string class because the string doesn't have any method which modifies its content. Every method creates new instance of string. And that is the thing I wrote in my first post. If you don't use ref keyword, you are not able to assign new value to that parameter...

Just for demonstration look at this:

void Func(Cls obj)
{
obj = new Cls();
obj.Str = "New instance of class";
}


When you rewrite the function as above, the obj object declared and created in the Run() function will not be modified.

--> in your example 'cls ' object is alive within boundary of main ..
--> so .. it has to change the member ... its nothing new ...

And where it should be alive???? What are you talking about???
If you pass any object or value-type variable to the function, that object or variable has to be alive in the scope where you are calling that function!!!

So I try to write the diferences between ref and non-ref passing again...

Lets suppose, we are talking about the reference types. Reference types are all classes. Structures and build-in single types (not string) are called value-types and the following is not valid for them...

1.)
Whenever you pass any object into the function without ref keyword, you pass reference to that object.

You can modify the object inside the function. You can chage everything you are allowed to chage (any public variables or non-public variables if they are accessible through public properties or functions...).

However, you cannot assign new value into that parameter. Yes, you can, however that change will not be applied to the variable you pass to the function...

2.) Whenever you pass any object using ref keyword, method will refer to exactely the same variable as that passed into the method... So you can modify its content as well as you can create new instance of class and assign it there...

It means, whenever you are passing erence types into any function using any kind of passing, you pass the reference. You don't make copy of that object!!!!

Please, check it before you answer! It is really true!!!

Martin

pareshgh
March 10th, 2003, 12:38 PM
i agree that
objects will be passed as reference automatically since in java is also a same case ... but String is also the same case then why function can't modify the original string...

Paresh

MartinL
March 10th, 2003, 12:40 PM
I wrote already!

String is written in such way. It has no members you can use for modifying its content... Every member of string class will create new instance of string... And by the way, it is good that they decided to implement string in this way... :)

Martin

pareshgh
March 10th, 2003, 12:41 PM
Okay !!

MartinL
March 10th, 2003, 12:42 PM
Additionaly, even you can write class that will offer just function which don't modify any content/data-members of the object. It is the design decision of the class...

martin

pareshgh
March 10th, 2003, 12:45 PM
hmm, i knew this but had a question abt that stupid string so that FYI i realized that string hasn't inner members...whereas class object's has and is passed by ref.

but then next obvious question would be
what's the diff btw passin obj as general and by ref keyword ??

Paresh:D

underwar
March 10th, 2003, 12:46 PM
agree that objects will be passed as reference automatically since in java is also a same case ... but String is also the same case then why function can't modify the original string...

Paresh


System.Text.StringBuilder is a string class which you can modify without creating new one

pareshgh
March 10th, 2003, 12:48 PM
yes, actually... good point here
;)

MartinL
March 10th, 2003, 12:54 PM
No...

if you read the documentation you will get the information that:
"This class represents a string-like object whose value is a mutable sequence of characters." :)

It is really not a string. Internally it doesn't use string to hold content of the StringBuilder class. And you have to convert that class into the string using ToString() member...

So you cannot modify string content using that class.

There is really no way to modify existing instance of the string class... Maybe weird, but it is true!

martin

underwar
March 10th, 2003, 12:56 PM
Didn't meant to say that its exactly like string.

MartinL
March 10th, 2003, 12:58 PM
Yes... OK...

However you cannot modify string's value using it... :D You can just create new instance of string... :D :D :D

MartinL
March 10th, 2003, 01:01 PM
Yeah guys... I made one mistake...

StringBuilder uses internally string. I am looking into its sources now... :)

However after every operation with StringBuidler it calls function ReplaceString. This is its body:

private void ReplaceString(int tid, String value) {
BCLDebug.Assert(value!=null, "[StringBuilder.ReplaceString]value!=null");

m_currentThread = tid; // new owner
m_StringValue = value;
}


So it creates new instance of string class everytime you make some changes in content of StringBuidler... :D :D :D

Martin

underwar
March 10th, 2003, 01:09 PM
lol. sounds like something that m$ wrote :)

pareshgh
March 10th, 2003, 06:51 PM
so in the assence stringbuilder takes more memory...
Paresh

aspdotnet
March 10th, 2003, 10:04 PM
although string class is reference type, it use like a value type..

hehe...

MartinL
March 11th, 2003, 02:06 AM
Originally posted by pareshgh
so in the assence stringbuilder takes more memory...
Paresh

Who in MS cares about memory now??? :D

pareshgh
March 11th, 2003, 11:48 AM
yea, memory management is all done and taken care by .NET layers now. so need to worry about memory now :D ,

GC is taking care of all ...

by the way martin - i also like this :D
character .. so funny and so laughing .. showing all its teeth...:D