Pergunta

Eu entendo que se eu passar um tipo de valor (int, struct, etc.) como um parâmetro (sem a palavra-chave ref), uma cópia dessa variável é passado para o método, mas se eu usar a palavra-chave ref um referência a essa variável é passado, não um novo.

Mas, com referência tipos, como classes, mesmo sem a palavra-chave ref, uma referência é passado para o método, não uma cópia. Então, o que é o uso da palavra-chave ref com referência tipos?


Tome por exemplo:

var x = new Foo();

Qual é a diferença entre o seguinte?

void Bar(Foo y) {
    y.Name = "2";
}

e

void Bar(ref Foo y) {
    y.Name = "2";
}
Foi útil?

Solução

Você pode mudar o que foo pontos para usando y:

Foo foo = new Foo("1");

void Bar(ref Foo y)
{
    y = new Foo("2");
}

Bar(ref foo);
// foo.Name == "2"

Outras dicas

Há casos em que você deseja modificar o real referência e não o objeto apontado:

void Swap<T>(ref T x, ref T y) {
    T t = x;
    x = y;
    y = t;
}

var test = new[] { "0", "1" };
Swap(ref test[0], ref test[1]);

Jon Skeet escreveu um ótimo artigo sobre passagem de parâmetros em C #. Ele detalha claramente o comportamento exato e uso de passagem de parâmetros por valor, por referência (ref), e pela saída (out).

Aqui está uma citação importante a partir dessa página em relação aos parâmetros ref:

parâmetros

Referência não passar no Os valores das variáveis ??usadas no função membro invocação - eles usam as próprias variáveis. Ao invés de criação de um novo local de armazenamento para a variável em função do membro declaração, o mesmo local de armazenamento é utilizado, de modo que o valor da variável no elemento de função e o valor do parâmetro de referência será sempre ser o mesmo. parâmetros de referência necessidade o modificador ref como parte tanto do declaração e a invocação - que significa que é sempre claro quando você está passando algo por referência.

Muito bem explicado aqui: http://msdn.microsoft.com/en-us/library/s6938f28.aspx

Abstract do artigo:

Uma variável de um tipo de referência não contêm os dados directamente; isto contém uma referência aos seus dados. Quando você passar um tipo de referência parâmetro por valor, é possível alterar os dados apontado pelo a referência, tal como o valor de um membro da classe. No entanto, você não pode alterar o valor da própria referência; isto é, você não pode usar a mesma referência para alocar memória para uma nova classe e tê-lo persistir fora do bloco. Para fazer isso, passar o parâmetro usando o ref ou out palavra-chave.

Quando você passar um tipo de referência com a palavra-chave ref, você passar a referência por referência, eo método que você chama pode atribuir um novo valor para o parâmetro. Essa mudança irá propagar para o escopo de chamada. Sem ref, a referência é passado por valor, e isso não acontece.

C # também tem o 'fora' palavra-chave que é muito parecido com ref, só que com 'ref', os argumentos devem ser inicializados antes de chamar o método, e com 'fora' é necessário atribuir um valor no método de recepção.

Ele permite que você modificar a referência passada. Por exemplo.

void Bar()
{
    var y = new Foo();
    Baz(ref y);
}

void Baz(ref Foo y)
{
    y.Name = "2";

    // Overwrite the reference
    y = new Foo();
}

Você também pode usar a se você não se preocupam com a referência passou em:

void Bar()
{
    var y = new Foo();
    Baz(out y);
}

void Baz(out Foo y)
{
    // Return a new reference
    y = new Foo();
}

Outro monte de código

class O
{
    public int prop = 0;
}

class Program
{
    static void Main(string[] args)
    {
        O o1 = new O();
        o1.prop = 1;

        O o2 = new O();
        o2.prop = 2;

        o1modifier(o1);
        o2modifier(ref o2);

        Console.WriteLine("1 : " + o1.prop.ToString());
        Console.WriteLine("2 : " + o2.prop.ToString());
        Console.ReadLine();
    }

    static void o1modifier(O o)
    {
        o = new O();
        o.prop = 3;
    }

    static void o2modifier(ref O o)
    {
        o = new O();
        o.prop = 4;
    }
}

Além das respostas existentes:

Como você perguntou para a diferença dos 2 métodos: Não há co (ntra) variância ao usar ref ou out:

class Foo { }
class FooBar : Foo { }

static void Bar(Foo foo) { }
static void Bar(ref Foo foo) { foo = new Foo(); }

void Main()
{
    Foo foo = null;
    Bar(foo);           // OK
    Bar(ref foo);       // OK

    FooBar fooBar = null;
    Bar(fooBar);        // OK (covariance)
    Bar(ref fooBar);    // compile time error
}

Um parâmetro em um método parece estar sempre passando uma cópia, a questão é uma cópia do que. Uma cópia é feita por um construtor de cópia para um objeto e uma vez que todas as variáveis ??de objeto em C #, eu acredito que este é o caso para todos eles. Variáveis ??(objetos) são como as pessoas que vivem em alguns endereços. Nós, quer mudar as pessoas que vivem nesses endereços ou podemos criar mais referências para as pessoas que vivem nesses endereços no livro de telefone (cópias make rasas). Assim, mais do que um identificador pode referir-se ao mesmo endereço. tipos de referência desejam mais espaço, tipos de valor tão diferente que estão diretamente conectados por uma flecha ao seu identificador na pilha, eles têm valor para outro endereço na pilha (um espaço maior para habitar). Este espaço deve ser tomado a partir do heap.

Tipo de valor: Identificador (contém valor = endereço do valor pilha) ----> Valor do tipo de valor

tipo de referência: Identifier (contém valor = endereço do valor pilha) ----> (contém valor = endereço do valor montão) ----> valor Heap (na maioria das vezes contém endereços para outros valores), imagine mais flechas fincadas em diferentes direções a matriz [0], matriz [1], matriz [2]

A única maneira de alterar um valor é seguir as setas. Se uma seta se perde / mudou na forma como o valor é inacessível.

Variáveis ??

Referência carregam o endereço de um lugar para outro de modo que qualquer updation sobre eles em qualquer lugar vai refletir sobre todos os lugares então o que é o uso de REF. variável de referência (405) são bons até nenhuma nova memória é alocada para a variável de referência passou no método.

Uma vez que nova memória alocar (410), em seguida, a alteração do valor neste objeto (408) não refletirá em todos os lugares. Por esta ref vem. Ref é referência de referência, de modo sempre novo memória alocá-lo a conhecer, porque ele está apontando para esse local, portanto, o valor pode ser compartilhado por todos. Você pode ver a imagem para mais clearity.

Ref na variável de referência

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top