문제

객체를 메소드에 전달하는 경우 왜 ref 키워드를 사용해야 합니까?어쨌든 이것이 기본 동작이 아닌가?

예를 들어:

class Program
{
    static void Main(string[] args)
    {
        TestRef t = new TestRef();
        t.Something = "Foo";

        DoSomething(t);
        Console.WriteLine(t.Something);
    }

    static public void DoSomething(TestRef t)
    {
        t.Something = "Bar";
    }
}


public class TestRef
{
    public string Something { get; set; }
}

출력은 "Bar"입니다. 이는 개체가 참조로 전달되었음을 의미합니다.

도움이 되었습니까?

해결책

통과 ref 객체가 무엇인지 변경하려면 다음을 수행하십시오.

TestRef t = new TestRef();
t.Something = "Foo";
DoSomething(ref t);

void DoSomething(ref TestRef t)
{
  t = new TestRef();
  t.Something = "Not just a changed t, but a completely different TestRef object";
}

DoSomething을 호출한 후, t 원본을 언급하지 않습니다 new TestRef, 그러나 완전히 다른 개체를 나타냅니다.

불변 객체의 값을 변경하려는 경우에도 유용할 수 있습니다.ㅏ string.값을 변경할 수 없습니다. string 일단 생성되면.하지만 ref, 다른 값을 가진 다른 문자열의 문자열을 변경하는 함수를 만들 수 있습니다.

편집하다:다른 사람들이 언급했듯이.사용하는 것은 좋지 않습니다. ref 꼭 필요한 경우가 아니면.사용 ref 메소드가 다른 인수를 변경할 수 있는 자유를 제공하는 경우, 메소드 호출자는 이러한 가능성을 처리하도록 코딩해야 합니다.

또한 매개변수 유형이 객체인 경우 객체 변수는 항상 객체에 대한 참조 역할을 합니다.이는 다음을 의미합니다. ref 키워드를 사용하면 참조에 대한 참조가 있습니다.이를 통해 위에 제공된 예제에 설명된 대로 작업을 수행할 수 있습니다.그러나 매개변수 유형이 기본 값인 경우(예: int), 이 매개변수가 메소드 내에서 할당되면 메소드가 반환된 후 전달된 인수의 값이 변경됩니다.

int x = 1;
Change(ref x);
Debug.Assert(x == 5);
WillNotChange(x);
Debug.Assert(x == 5); // Note: x doesn't become 10

void Change(ref int x)
{
  x = 5;
}

void WillNotChange(int x)
{
  x = 10;
}

다른 팁

"값별로 참조 전달"과 "참조로 매개 변수/인수 전달"을 구별해야합니다.

나는 a 주제에 대한 합리적으로 긴 기사 뉴스 그룹에 등장 할 때마다 신중하게 글을 쓰지 않으려면 :)

.NET에서 매개 변수를 메소드로 전달하면 사본이 생성됩니다. 값 유형에서 값에 대한 수정이 메소드 범위에 있으며 메소드를 종료 할 때 손실됩니다.

참조 유형을 전달할 때 사본도 만들어 지지만 참조 사본입니다. 즉, 동일한 개체에 대한 메모리에 두 개의 참조가 있습니다. 따라서 참조를 사용하여 객체를 수정하면 수정됩니다. 그러나 참조 자체를 수정하면 사본임을 기억해야합니다. 방법을 종료하면 변경 사항도 손실됩니다.

사람들이 전에 말했듯이 과제는 참조의 수정이므로 손실됩니다.

public void Method1(object obj) {   
 obj = new Object(); 
}

public void Method2(object obj) {  
 obj = _privateObject; 
}

위의 방법은 원래 객체를 수정하지 않습니다.

예제의 약간의 수정

 using System;

    class Program
        {
            static void Main(string[] args)
            {
                TestRef t = new TestRef();
                t.Something = "Foo";

                DoSomething(t);
                Console.WriteLine(t.Something);

            }

            static public void DoSomething(TestRef t)
            {
                t = new TestRef();
                t.Something = "Bar";
            }
        }



    public class TestRef
    {
    private string s;
        public string Something 
        { 
            get {return s;} 
            set { s = value; }
        }
    }

TestRef는 클래스 (참조 객체)이므로 TER로 전달하지 않고 T 내부의 내용을 변경할 수 있습니다. 그러나 T를 Ref로 통과하면 TestRef는 원래 T가 참조하는 것을 변경할 수 있습니다. 즉, 다른 객체를 가리 키게 만듭니다.

와 함께 ref 당신은 쓸 수 있습니다:

static public void DoSomething(ref TestRef t)
{
    t = new TestRef();
}

메소드가 완료된 후 T가 변경됩니다.

변수를 생각하십시오 (예 : foo참조 유형의 (예 : List<T>) 보유로 객체 식별자 "Object #24601"형식의 형식. 진술을 가정하십시오 foo = new List<int> {1,5,7,9}; 원인 foo "Object #24601"(4 개 항목이있는 목록)을 고정하려면. 그런 다음 전화합니다 foo.Length 객체 #24601은 길이를 요청하면 4에 응답 할 것입니다. foo.Length 4와 같다.

만약에 foo 사용하지 않고 메소드로 전달됩니다 ref,이 방법은 객체 #24601을 변경할 수 있습니다. 그러한 변화의 결과로 foo.Length 더 이상 동일하지 않을 수 있습니다. 4. 방법 자체는 변경할 수 없습니다. foo, "개체 #24601"을 계속 유지합니다.

통과 foo A로 ref 매개 변수는 호출 된 메소드가 객체 #24601뿐만 아니라 foo 그 자체. 이 메소드는 새 개체 #8675309를 생성하고 이에 대한 참조를 저장할 수 있습니다. foo. 그렇다면 foo 더 이상 "객체 #24601"을 유지하지 않고 대신 "객체 #8675309".

실제로, 기준 유형 변수는 "Object #8675309"형식의 문자열을 보유하지 않습니다. 그들은 의미있게 숫자로 변환 할 수있는 것을 가지고 있지도 않습니다. 각 기준 유형 변수는 비트 패턴을 보유 할 것이지만, 이러한 변수에 저장된 비트 패턴과 그들이 식별하는 객체 사이에는 고정 된 관계가 없습니다. 코드가 객체 나 참조에서 정보를 추출 할 수있는 방법은 없으며, 코드가 원래 객체를 식별하는 참조를 보유하거나 알지 않는 한, 다른 참조가 동일한 개체를 식별했는지 여부를 결정합니다.

이것은 C.의 포인터로 포인터를 전달하는 것과 같습니다. 몸소 .NET에서 그렇게한다면 디자인 문제가있을 것 같아요!

사용함으로써 ref 참조 유형의 키워드 참조에 대한 참조를 효과적으로 전달합니다. 여러면에서 그것은 사용과 동일합니다. out 키워드이지만이 방법이 실제로 무엇이든 할당 할 것이라는 보장이 없다는 사소한 차이가 있습니다. ref'Ed 매개 변수.

ref 두 가지 범위를위한 글로벌 영역으로 모방 (또는 동작) :

  • 방문객
  • 칼리.

그러나 가치를 전달하는 경우 상황이 다릅니다. 참조로 값을 전달할 수 있습니다. 이를 통해 정수를 메소드로 전달하고 방법이 귀하를 대신하여 정수를 수정하도록합니다.

Ref는 함수가 객체 자체에 손을 대는 것인지 아니면 그 값에만 손을 넣을 수 있는지를 나타냅니다.

참조로 통과하는 것은 언어에 묶여 있지 않습니다. 그것은 패스 별 옆에있는 매개 변수 바인딩 전략입니다. 패스 이름별로, Pass By Need 등 ...

사이드 노트 : 클래스 이름 TestRef 이 맥락에서 끔찍하게 나쁜 선택입니다;).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top