tags:

views:

160

answers:

5

Hi, I have bit confusion about parameters. When we should have to use reference parameter and when should have to use value type parameters while programming with methods/functions in c# ?

A: 

If you use a value type parameter you won't be able to change its value inside the method (you can but this won't reflect to the variable used to call the method), while with reference types you could change the value.

Darin Dimitrov
+14  A: 

You need to be very clear on the distinction between reference types vs value types, and "by value" parameters vs "by reference" parameters.

I have articles on both topics:

The two interact somewhat when using a "by value" parameter which is a reference type: in this case the value which copied by value is the reference itself; you can still modify the object that the reference refers to:

void SomeMethod(StringBuilder x)
{
    x.Append("Modified");
}
...

StringBuilder builder = new StringBuilder();
SomeMethod(builder);
Console.WriteLine(builder.ToString()); // Writes "Modified"

Note that this isn't the same thing as pass-by-reference semantics... if SomeMethod were changed to include:

x = null;

then that wouldn't make the builder variable null. However, if you also changed the x parameter to be ref StringBuilder x (and changed the calling code appropriately) then any changes to x (such as setting it to null) would be seen by the caller.

When designing your own API, I would strongly advise you to almost never use ref or out parameters. They can be useful occasionally, but usually they're an indication that you're trying to return multiple values from a single method, which is often better done with a type specifically encapsulating those values, or perhaps a Tuple type if you're using .NET 4. There are exceptions to this rule, of course, but it's a good starting point.

Jon Skeet
I'm so glad C# has the `ref` keyword. Python has been a nightmare because I couldn't do what I wanted to.
Mark
+1 to never use the ref or out parameters.
Aseem Gautam
@Mark: I'm glad it's available where necessary... I just don't like using it very often.
Jon Skeet
I would probably not use a Tuple as either an input or output to any methods in my api. The Tuple requires that you interpret the generic arguments i.e. Tuple<string, int, Account> you then know that Item1 is a string, Item2 is an int and Item3 is an Account but I would rather go with encapsulating them in class specifically for that purpose
Ian Johnson
@Ian: It depends on the API in question. Consider `int.TryParse`... these days that could have returned a `Nullable<int>` or a `Tuple<bool, int>`... either of those would be fine IMO; no need to have a separate type to encapsulate those.
Jon Skeet
@John I see your point that the tuple is better than the out parameter though I would prefer the generic class ParseResult<int> with the properties Successful and Value. I am worried that Tuples are going to appear in APIs where a proper object is appropriate because of developer laziness
Ian Johnson
A: 

When you send a Value type parameter, then internally a copy of the original variable is sent to the function/method. So if you change the value inside that function, the original value of the variable (ourside your function where it is declared) remains intact.

When you send a Reference type parameter, then the function plays directly with the original value of that variable. This is because you send only the memory reference of that variable to your function.

so depending upon the scope of your variable and how you want to use that variable in your application, you can decide how to send it to your function. A good example could be.. when you want to count update some global counter or state kind of variable in your application, then it is good to send it by ref so that other functions will get the latest up to date value of that variable later.

Anil
A: 

Best article ever on this topic:

C# Heap(ing) Vs Stack(ing) in .NET: Part I

There are four parts.

Aseem Gautam
A: 

You can try the following simple code, I think it can help you get a better understanding about when to use by-reference parameters.

using System.Collections.Generic;
using System.Diagnostics.Contracts;

class Program
{
    static void Main(string[] args)
    {
        var list = new List<int>(new[] { 1, 2, 3, 4 });

        MakeItNull(list);
        Contract.Assert(list != null);

        MakeItRealNull(ref list);
        Contract.Assert(list == null);
    }


    static void MakeItNull(List<int> list)
    {
        list = null;
    }

    static void MakeItRealNull(ref List<int> list)
    {
        list = null;
    }
} 
Hiber