Share via


Como saber a diferença entre passar um struct e passar uma referência de classe para um método (Guia de Programação em C#)

O exemplo a seguir demonstra como passando um struct para um método difere passando um classe instância para um método. No exemplo, ambos os argumentos (instância de classe e destruct ) são passados por valor e os dois métodos de alterar o valor de um campo do argumento. No entanto, os resultados dos dois métodos não são iguais porque o que é passado quando você passa uma struct difere o que é passado quando você passa uma instância de uma classe.

Porque uma struct é um tipo de valor, quando você passar uma struct pelo valor de para um método, o método recebe e opera em uma cópia doargumento struct. O método não tem acesso ao original struct no método de chamada e, portanto, não é possível alterá-lo de forma alguma. O método pode alterar apenas a cópia.

Uma instância da classe é um tipo de referência, não é um tipo de valor. Quando um tipo de referência é passado por valor de para um método, o método recebe uma cópia da referência à instância da classe . Ou seja, o método recebe uma cópia do endereço da instância, não uma cópia da própria instância. A instância da classe no método de chamada possui um endereço, o parâmetro no método chamado possui uma cópia do endereço e os dois endereços se referir ao mesmo objeto. Como o parâmetro contém apenas uma cópia do endereço, o método chamado não é possível alterar o endereço da instância da classe no métodode chamada. No entanto, o chamado método pode usar o endereço para acessar os membros de classe que referenciam o endereço original e a cópia. Se o método chamado for alterado para um membro da classe , também altera a instância da classe original no método de chamada.

A saída de exemplo a seguir ilustra a diferença. O valor da willIChangeo campo da instância da classe é alterado pela chamada ao método ClassTaker como o método usa o endereço no parâmetro para localizar o campo especificado da instância da classe . O willIChange campo do struct no método de chamada não é alterado pela chamada ao método StructTaker como o valor do argumento é uma cópia do struct propriamente dito, não uma cópia do seu endereço. StructTakeras alterações na cópia e a cópia é perdido quando a chamada para StructTaker for concluída.

Exemplo

class TheClass
{
    public string willIChange;
}

struct TheStruct
{
    public string willIChange;
}

class TestClassAndStruct
{
    static void ClassTaker(TheClass c)
    {
        c.willIChange = "Changed";
    }

    static void StructTaker(TheStruct s)
    {
        s.willIChange = "Changed";
    }

    static void Main()
    {
        TheClass testClass = new TheClass();
        TheStruct testStruct = new TheStruct();

        testClass.willIChange = "Not Changed";
        testStruct.willIChange = "Not Changed";

        ClassTaker(testClass);
        StructTaker(testStruct);

        Console.WriteLine("Class field = {0}", testClass.willIChange);
        Console.WriteLine("Struct field = {0}", testStruct.willIChange);

        // Keep the console window open in debug mode.
        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}
/* Output:
    Class field = Changed
    Struct field = Not Changed
*/

Consulte também

Referência

Classes (Guia de Programação em C#)

Structs (Guia de Programação em C#)

Passando parâmetros (Guia de Programação em C#)

Conceitos

Guia de Programação em C#