Paso de parámetro predeterminado en C #

Maybe an old question, but am not finding anything comprehensive on the internet.

If the default parameter passing method in C# is Por valor, then how does it affect the initial Reference Type variable?

I.e. in the below example, why will it print "Hello World" instead of just "Hello", if it was parameter passing by value?

void Foo (StringBuilder x)
{
    x.Append (" World");
}   

StringBuilder y = new StringBuilder();
y.Append ("Hello");
Foo (y);
Console.WriteLine (y);

preguntado el 08 de noviembre de 11 a las 10:11

The reference to the string builder object is passed by value. -

6 Respuestas

First, understand that in C# there are two fundamental types: Tipos de valor y Tipos de referencia.

Furthermore, each of those types can be passed to a method Por valor or Por referencia. (So, that means there are actually cuatro maneras to pass a parameter to a method.)

And regardless of how you pass a Reference Type (By Value or by Reference), you have the ability to change the value to which that reference points!

Now, with regard to your particular example, your parameter of question is of type StringBuilder which is a Reference Type. (StringBuilder es una Clase and Classes are Reference Types.) And again, because you are passing a Reference Type to your method, you are able to change the value associated with that reference inside of that method.

Finally, note that you are passing your Reference Type parameter By Value. If instead you were to pass your Reference Type Por referencia y luego configúrelo en null, you would actually destroy the value associated with the reference. (That would be the same as setting the parameter variable to null afuera of the method.)

You can find a more more thorough and very readable explanation here: Conceptos de C #: valores frente a tipos de referencia

contestado el 14 de mayo de 19 a las 15:05

That parameter is still a pass-by-value but parameter variable x has a reference of the StringBuilder objeto.

The reference variable y has the reference of StringBuilder object

StringBuilder y = new StringBuilder();

and reference of StringBuilder object is copied to parameter x of Foo.

Foo (y);

respondido 08 nov., 11:14

Because StringBuilder is a mutable class and will passed by reference. Instead of string builder you use string it will be Hello because string is immutable. Also for value types like int, enum, ... there isn't any change.

For simplicity, Value types are struct, enum, primitive types, ... and reference types are classes, but As I mentioned there are some classes like string which are immutable and in fact, they will be passed by value.

respondido 08 nov., 11:14

Great! Thanks all for your quick and detailed answers. I was asked this question in a interview! and I was just validating my answer ;) So to sum-up: What is the default parameter passing method in C#... 1. Pass by Value for value types, Pass by reference for reference types (Now I know its not :), but I had said this as answer) 2. Pass by Value for immutable types, Pass by reference for mutable types 3. Pass by Value for primitive types, Pass by reference for non-primitive types 4. Or is it still something else? - ViV

@Vishruth In fact your answer is good enough, and I think this isn't a good interview question, if you can understand difference between value type and reference types, and immutable and mutable objects, is good enough, except they have too many interview and takes it as paper exam. - Saeed Amiri

Anything other than the primitive types (such as int, byte etc) are passed by reference by default. You are passing the same StringBuilder instancia al método.

respondido 08 nov., 11:14

They will be passed by reference but if they are immutable, there is no change on them. for example string is not primitive type, but there is no change in it's value. - Saeed Amiri

-1: the reference is passed by value, furthermore, there are non-primitive value-types such as DateTime. - Henrik

according to MSDN's own article, string is primitive msdn.microsoft.com/en-us/library/aa711900%28VS.71%29.aspx (first result when I type primitive types in .net to google). i know that the string instance is immutable in memory, but "to the user", it acts AS a primitive type. (DateTime is also primitive btw from the same perspective) - Can Poyrazoğlu

@Vishruth primitive types are the numeric types; integers and floating points. and types like string and datetime are also considered primitive in .net, in the sense that, if you pass them to a method, their value will be passed, and any changes you make to the passed values WON'T be reflected to the other (first) value at the other method. on the other hand, all the other types (as far as i remember) are references, where, when you pass them to a method, their "pointer" is copied, still "pointing to the same object in memory" - Can Poyrazoğlu

@canpoyrazoğlu Yes that was my mistake, but my point or Henrik point is that there are other types than what you said and they are value type, in fact we don't have primitive type / non primitive for separating way of their calling, these are sub class of general rule, Value Types and Reference Types, all structs are value type but not primitive ... - Saeed Amiri

StringBuilder is a class, so it will be passed by reference.

leer más: Value vs reference types

respondido 08 nov., 11:14

Compare the following. First with StringBuilder (reference type):

    public struct Tmd
    {
        public StringBuilder sb;
    }

    public void DoIt(Tmd a)
    {
        a.sb.Append(" World!");
    }

    public void Main()
    {
        Tmd a = new Tmd();
        a.sb = new StringBuilder();
        a.sb.Append("Hello");
        DoIt(a);
        Console.WriteLine(a.sb); // Hello World
    }

Here the struct is copied, as is the reference to the StringBuilder along with it, but the StringBuilder itself is not copied.

And now with a mutable struct (value type):

    public struct EvilMutable
    {
        public int i;
    }

    public struct Tmd
    {
        public EvilMutable em;
    }

    public void DoIt(Tmd a)
    {
        a.em.i += 1;
    }

    public void DoIt(EvilMutable em)
    {
        em.i += 1;
    }

    public void Main()
    {
        Tmd a = new Tmd();
        a.em.i += 5;
        Console.WriteLine(a.em.i); // 5
        DoIt(a);
        Console.WriteLine(a.em.i); // 5 (unchanged)
        DoIt(a.em);
        Console.WriteLine(a.em.i); // 5 (unchanged)
    }

In this case everything copied. However if we change this into a reference type:

    public class Tmd
    {
        public EvilMutable em;
    }

Then, we'll get this:

        Tmd a = new Tmd();
        a.em.i += 5;
        Console.WriteLine(a.em.i); // 5
        DoIt(a);
        Console.WriteLine(a.em.i); // 6
        DoIt(a.em);
        Console.WriteLine(a.em.i); // 6 (unchanged)

Respondido 02 Oct 12, 19:10

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.