IT박스

C #에서 참조 유형 변수에 "ref"를 사용하는 것은 무엇입니까?

itboxs 2020. 5. 30. 22:29
반응형

C #에서 참조 유형 변수에 "ref"를 사용하는 것은 무엇입니까?


키워드가 없는 매개 변수로 값 유형 ( int, struct등)을 ref전달하면 해당 변수의 사본이 메소드에 전달되지만 ref키워드를 사용하면 해당 변수에 대한 참조가 전달됩니다. 새로운 것이 아닙니다.

그러나 ref키워드가 없어도 클래스와 같은 참조 유형을 사용 하면 사본이 아닌 메소드에 참조가 전달됩니다. 그렇다면 ref키워드를 참조 유형과 함께 사용하는 것은 무엇 입니까?


예를 들어 보자.

var x = new Foo();

다음의 차이점은 무엇입니까?

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

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

foo사용 하는 포인트를 변경할 수 있습니다 y.

Foo foo = new Foo("1");

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

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

실제 참조 를 수정하려는 경우가 있지만 대상이 아닌 오브젝트는 다음과 같습니다.

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은 C #에서 매개 변수 전달에 대한 훌륭한 기사를 썼습니다 . 값, 참조 ( ref) 및 출력 ( out) 별로 매개 변수 전달의 정확한 동작 및 사용법을 명확하게 설명합니다 .

다음은 ref매개 변수 와 관련하여 해당 페이지에서 중요한 인용문입니다 .

참조 매개 변수는 함수 멤버 호출에 사용 된 변수의 값을 전달하지 않습니다. 변수 자체를 사용합니다. 함수 멤버 선언에서 변수의 새 스토리지 위치를 작성하는 대신 동일한 스토리지 위치가 사용되므로 함수 멤버의 변수 값과 참조 매개 변수의 값은 항상 동일합니다. 참조 매개 변수에는 선언과 호출의 일부로 ref 수정자가 필요합니다. 즉 참조로 무언가를 전달할 때 항상 명확합니다.


여기에 아주 잘 설명되어 있습니다 : http://msdn.microsoft.com/en-us/library/s6938f28.aspx

기사에서 요약 :

참조 유형의 변수는 데이터를 직접 포함하지 않습니다. 데이터에 대한 참조를 포함합니다. 참조 유형 매개 변수를 값으로 전달하면 클래스 멤버의 값과 같이 참조가 가리키는 데이터를 변경할 수 있습니다. 그러나 참조 자체의 값을 변경할 수는 없습니다. 즉, 동일한 참조를 사용하여 새 클래스에 메모리를 할당하고 블록 외부에 유지시킬 수 없습니다. 그렇게하려면 ref 또는 out 키워드를 사용하여 매개 변수를 전달하십시오.


ref 키워드로 참조 유형을 전달하면 참조로 참조를 전달하며 호출하는 메소드는 매개 변수에 새 값을 지정할 수 있습니다. 이 변경 사항은 호출 범위로 전파됩니다. ref가 없으면 참조가 값으로 전달되며 이러한 일이 발생하지 않습니다.

C #에는 ref와 비슷한 'out'키워드가 있습니다. 단, 'ref'를 사용하면 메소드를 호출하기 전에 인수를 초기화해야하며 'out'을 사용하면 수신 메소드에 값을 지정해야합니다.


전달 된 참조를 수정할 수 있습니다. 예 :

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

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

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

당신은 또한 사용할 수 있습니다 밖으로 참조가 전달에 대해 상관하지 않는 경우 :

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

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

또 다른 코드

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;
    }
}

기존 답변 외에도

당신이이 방법의 차이에 대한 질문과 같이 사용에는 공동 (NTRA) 차이가 없습니다 ref또는 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
}

A parameter in a method seems to be always passing a copy, the question is a copy of what. A copy is done by a copy constructor for an object and since all variables are Object in C#, i believe this is the case for all of them. Variables(objects) are like people living at some addresses. We either change the people living at those addresses or we can create more references to the people living at those addresses in the phone book(make shallow copies). So, more than one identifier can refer to the same address. Reference types desire more space, so unlike value types that are directly connected by an arrow to their identifier in the stack, they have value for another address in the heap( a bigger space to dwell). This space needs to be taken from the heap.

Value type: Indentifier(contains value =address of stack value)---->Value of value type

Reference type: Identifier(contains value=address of stack value)---->(contains value=address of heap value)---->Heap value(most often contains addresses to other values), imagine more arrows sticking in different directions to Array[0], Array[1], array[2]

The only way to change a value is to follow the arrows. If one arrow gets lost/changed in the way the value is unreachable.


Reference Variables carry the address from one place to another so any updation on them at any place will reflect on all the places THEN what is the use of REF. Reference variable (405) are good till no new memory is allocated to the reference variable passed in the method.

Once new memory allocate (410) then the value change on this object (408) will not reflect everywhere. For this ref comes. Ref is reference of reference so whenever new memory allocate it get to know because it is pointing to that location therefore the value can be shared by everyOne. You can see the image for more clearity.

Ref in Reference Variable

참고URL : https://stackoverflow.com/questions/961717/what-is-the-use-of-ref-for-reference-type-variables-in-c

반응형