Behavior of parameters in class constructor in C #

4

I'm having a question regarding the behavior of the parameters passed to the constructor of a class, are they by default ref / out or value? Searching about the behavior of parameters in common methods they are by default values, as this example says:

link

But when I created this example, I realize that what I do outside the scope of the class changes the state of ownership of the instance, which is private. Is that correct?

public class escopo
{
    public void Controller()
    {
        var lista = CriarLista();
        var teste = new teste(lista);

        lista[0] = "Example";

        teste.testeVeridico();
    }

    public List<String> CriarLista()
    {
        var lista = new List<String>() { "A", "B", "C", "D", "E" };
        return lista;
    }
}

public class teste
{
    private List<String> Lista { get; set; }

    public teste(List<String> lista)
    {
        Lista = lista;
    }

    public bool testeVeridico()
    {
        //retorna true
        return Lista[0] == "Example";
    }
}
    
asked by anonymous 30.09.2015 / 22:23

2 answers

4

Parameters are by value. At least this is the default. But his type of data influences his behavior. You have types that are by value and types that are by reference .

Do not confuse parameter passing with type allocation. Going by value is not the same as having one type by value.

Passing by value means that a copy of the data is made.

Value types do what you expect since there is a copy of the data you see.

The types by reference are also passed by value. But what is the value of the types by reference? It is a pointer to an object in heap . It's a memory address. Ever. Then the copy is also made, but it is the address that is copied, not the object referenced. It's for value too.

The difference is that this type has an object with a longer lifetime. Internally the value is pointer, but in your code you access this object pointed to by it. Any change in it, reflects on the object throughout its lifetime, even outside the method where the change occurred. This is a characteristic of type and not of parameter passing.

Note that if you change the object's address, then you'll see that there was no change in argument last for the method, either constructor or not.

I created an example to demonstrate this:

public void OutroTeste(List<string> lista) {
    lista = new List<string>() { "aaa", "bbb" };
    return;
}

See running on dotNetFiddle .

This method is receiving lista by value. Then it creates a new list with completely different data inside it and you have to save it to lista which is the parameter. When I am accessing the list after I ran this method, what happens? This new data is gone. The new list only exists within the method, even though I have assigned it to the parameter, it has not been changed, because this time I actually flipped the parameter. When you change the elements of the same list that the parameter points to, you are changing the object pointed to and not the parameter itself.

Learn more about their placement .

In your example List<T> is a type by reference, it's a class. Then everything you change in it will be reflected in the variable that was used as an argument.

A curious type is string . It is a reference, so the pointer is always passed. But it is immutable and has value semantics, so a change in the object will create a new object that will be allocated in another position from memory. Therefore the change will be restricted to the method where this occurred. Unless, of course, the parameter is marked as a reference.

Parameters ref

out and ref are used to pass by reference . There will always be a reference, for the real value. In the case of types by reference, there will be a reference to the type pointer that is still a reference to the object itself. In this case even in the example above if a new object is created, this will reflect outside the method.

So types by value or types by reference can make use of passing by reference.

If you're curious to understand how stack works and heap in> .

    
30.09.2015 / 22:30
0

I think the confusion is in Primal Types and Objects ...

Primitive Types

Parameters of primitive types (int, string, bool and etc ...) are always passed as values, for example:

    static void Main(string[] args)
    {
        String tipoString = "Valor do Tipo Primitivo";
        Int32 tipoInt = 50;

        //Alterações nos valores?
        MetodoString(tipoString);
        MetodoInt(tipoInt);

        Console.WriteLine(tipoString); // Valor do Tipo Primitivo
        Console.WriteLine(tipoInt); // 50
    }

    static void MetodoString(String aParametro)
    {
        //Neste caso esta mudança apenas e valida neste escopo
        //Pois o parametro do tipo String e passado como Valor
        aParametro = "Mudança de Valor";
    }

    static void MetodoInt(Int32 aParametro)
    {
        //O mesmo ocorre neste caso
        aParametro = 10;
    }

As seen above both the String value and the Integer have not been changed when passed by parameter. This occurs because during the passing of the parameter and made a copy of the value of String "typeString".

Now with objects, the story changes a little ...

Objects

Parameters of objects such as (Lists, Controls, Classes Created by Yourself!) are passed through Reference .

How do I reference?

When you pass one list per parameter, you do not have a copy of all its values, but only one address is pointed at it, that is, just a reference! for example:

    static void Main(string[] args)
    {
        List<String> listaString = new List<String>() { "A", "B", "C" };

        //Alterações nos valores?
        MetodoString(listaString);

        //Comando que impirmi todos os valores da Lista
        listaString.ForEach(f => Console.WriteLine(f)); // A
                                                        // B
                                                        // C
                                                        // D
    }

    static void MetodoString(List<String> aParametroLista)
    {
        //Neste caso É adicionado o valor D na lista pois o Parametro "aParametroLista"
        //Apenas aponta pra minha real lista
        aParametroLista.Add("D");
    }

As seen above in the case of objects when passed by parameter are affected by the scope of the method.

But will it always be like this? Will primitive types always be passed by value and objects by reference?

The answer is no!

Ref

We can pass parameters of primitive types by reference using for example the command ref:

    static void Main(string[] args)
    {
        String tipoString = "Valor do Tipo Primitivo";

        //Alterações nos valores?
        MetodoString(ref tipoString);

        Console.WriteLine(tipoString); // Mudança de Valor
    }

    static void MetodoString(ref String aParametro)
    {
        // Neste caso o valor do parametro Será mudado pois isto é uma Referencia!
        // ou seja apenas um endereço
        aParametro = "Mudança de Valor";
    }

As seen above in this case even primitive values can be passed by reference.

If you are interested in these References ... Search for memory areas such as Stack and Heap

Search tip: What are and where are the" stack "and" heap "?

I hope I have helped! Good Studies

    
02.10.2015 / 04:48