Passando por ref e para fora
-
10-07-2019 - |
Pergunta
Então, se eu estou iteração usando um loop foreach e eu tenho um dentro função que leva um argumento do objeto iterado da lista, e digamos que eu defina seu valor como ser diferente. Por que eu não tenho que usar para fora ou ref? Eu pensei que ele só foi aprovada pelo valor se você não usar out ou ref .... eu sei que um ref você deve ter inicializado a variável antes e fora, você apenas tem que ter definido o seu valor antes do retorno do método.
Parece que se você uma iteração através de uma lista e passar um objeto em sua realmente passado por referência. Considere o exemplo a seguir.
Exemplo
class Program
{
static void Main(string[] args)
{
List<Foo> list = new List<Foo>();
list.Add(new Foo() { Bar = "1" });
list.Add(new Foo() { Bar = "2" });
foreach (var f in list)
{
Foo f2 = f;
Console.WriteLine("SetFoo Pre: " + f2.Bar);
SetFoo(f2);
Console.WriteLine("SetFoo Post: " + f2.Bar);
Console.WriteLine("SetFooRef Pre: " + f2.Bar);
SetFooRef(ref f2);
Console.WriteLine("SetFooRef Post: " + f2.Bar);
Console.WriteLine("");
}
Console.WriteLine("");
int i = 0;
// Not using ref keyword
Console.WriteLine("SetI Pre: " + i);
SetI(i);
Console.WriteLine("SetI Post: " + i);
// Using ref keyword
Console.WriteLine("SetRefI Pre: " + i);
SetRefI(ref i);
Console.WriteLine("SetRefI Post: " + i);
}
private static void SetRefI(ref int i)
{
i = 3;
Console.WriteLine("SetRefI Inside: " + i);
}
private static void SetI(int i)
{
i = 2;
Console.WriteLine("SetI Inside: " + i);
}
private static void SetFooRef(ref Foo f)
{
f.Bar = String.Format("{0} :: {1}", f.Bar, "WithRef");
Console.WriteLine("SetFooRef Inside: " + f.Bar);
}
private static void SetFoo(Foo f)
{
f.Bar = String.Format("{0} :: {1}", f.Bar, "WithoutRef");
Console.WriteLine("SetFoo Inside: " + f.Bar);
}
}
class Foo
{
public string Bar { get; set; }
}
Output:
setFoo Pre: 1 setFoo Interior: 1 ::
WithoutRef setFoo Post: 1 WithoutRef
SetFoo Pre: 1 :: WithoutRef setFoo
Interior: 1 :: WithoutRef :: comref
SetFoo Post: 1 WithoutRef :: comrefsetFoo Pre: 2 setFoo Interior: 2 ::
WithoutRef setFoo Post: 2 WithoutRef
SetFoo Pre: 2 :: WithoutRef setFoo
Interior: 2 :: WithoutRef :: comref
SetFoo Post: 2 WithoutRef :: comrefSETI Pre: 0 SETI Interior: 2 SetIPost: 0
SetRefI Pre: 0 SetRefI Interior: 3
SetRefI Post: 3
Eu entendo o árbitro com o exemplo inteiro, mas não o acima Foo exemplo objeto iteração.
Obrigado!
Solução
O referência é passado por valor. Assim, o método ainda pode alterar o conteúdo do objeto, ele só não pode mudar qual objeto a variável refere-se a.
Consulte meu artigo sobre a passagem de parâmetros para muito mais informação, juntamente com o meu artigo sobre tipos de referência e tipos de valor .