390

이 질문에는 이미 답변이 있습니다.

차이점은 무엇입니까?refout.NET의 매개 변수? 그 중 하나가 다른 것보다 더 유용 할 수있는 상황은 무엇입니까? 하나는 사용할 수 있고 다른 하나는 사용할 수없는 코드 스 니펫은 무엇입니까?

18 답변


479

그들은 거의 동일합니다. 유일한 차이점은out매개 변수는 초기화 할 필요는 없지만ref매개 변수는 무언가로 설정되어야합니다.

int x;
Foo(out x); // OK

int y;
Foo(ref y); // Error: y should be initialized before calling the method

Ref매개 변수는 수정 될 수있는 데이터를위한 것이며,out매개 변수는 함수에 대한 추가 출력 데이터입니다 (예 :int.TryParse)에 대해 이미 반환 값을 사용하고 있습니다.


  • 또한 호출 매개 변수를 실행하는 동안 호출자에게 반환하기 전에 out 매개 변수를 설정해야합니다. 이는 호출자가 호출하기 전에 호출자가 설정해야하는 ref와는 반대입니다. - Jesse C. Slicer
  • @Mike 귀하의 수정이 잘못되었습니다. 그것은 옳았다. "그리고아웃매개 변수를 설정해야합니다. " 를 수신하는 방법out매개 변수가 초기화해야합니다. 를 수신하는 방법ref매개 변수는 원하는대로 할 수 있습니다. 그것은 확실히 그것을 무시할 수 있습니다. 다시 롤백하고 있습니다. - xanatos
  • 분명히 주요한 차이점은 심판의 안팎을 가리키는 반면 심판의 바깥 쪽은 데이터를 반환하는 데에만 사용될 수 있다는 것입니다. 고려 void 동작 (ref int z) {Debug.WriteLine (z); } 및 void notWorks (out int z) {Debug.WriteLine (z); } 또는 초기화 된 전에 out 매개 변수의 값을 얻기위한 트릭이 누락 되었습니까? 디버거가 예를 들어 그것을 할 수있는 것을 나는 알아 차린다. - user159335
  • 그래서 중간에 뭔가를 설정해야하는 매개 변수에 대해서는 ref를 사용해야합니다. 그렇지 않으면 out을 사용하십시오. - FistOfFury
  • 위쪽에서 Ref는 함수 호출 중에 Struct의 추가 복사본을 저장할 수 있습니다. 단점은 클래스를 null로 초기화 할 수 있으므로 계속 보안을 유지해야합니다. - Michael Brown

124

왜 C #은 'ref'와 'out'을 모두 가지고 있습니까?

out 매개 변수를 사용하는 메서드 호출자는 호출 전에 out 매개 변수로 전달 된 변수에 할당 할 필요가 없습니다. 그러나 호출 수신자는 반환하기 전에 out 매개 변수에 할당해야합니다.

반대로 ref 매개 변수는 호출자가 처음에 할당 한 것으로 간주됩니다. 따라서 호출 수신자는 사용하기 전에 ref 매개 변수에 할당 할 필요가 없습니다. Ref 매개 변수는 메소드 안팎으로 전달됩니다.

그래서,out뜻밖에, 동안ref안과 밖을위한 것입니다.

이것들은[out][in,out]COM 인터페이스의 매개 변수,out매개 변수는 호출자가 호출되는 메소드에서 필요하지 않은 경우 미리 할당 된 객체를 전달할 필요가 없다는 것입니다. 이렇게하면 할당 비용과 마샬링과 관련된 비용 (COM에서는 더 많이 발생하지만 COM에서는 그렇지 않을 수 있습니다. .NET에서는 드문 경우).


  • 대조적으로, 대조 파라미터는 피 호출자에 의해 초기에 할당 된 것으로 간주된다 "는 것은 분명히"호출자 "를 의미한다. 귀하의 답변을 수정하려고 시도했지만 사소한 변경 사항을 저장하지 않으려 고합니다. - fpsColton
  • 링크에는이 차이점에 대한 매우 명확한 설명이 포함되어 있습니다. 대부분의 답변보다 좋습니다. 감사! - Hannish

82

refout둘 다 호출 된 메소드가 매개 변수를 수정할 수있게합니다. 그들 사이의 차이점은 무엇이 발생하는지입니다.전에너는 전화한다.

  • ref매개 변수에 값이 있음을 의미합니다.전에함수로 들어갑니다. 호출 된 함수는 언제든지 값을 읽고 변경할 수 있습니다.매개 변수가 입력 된 다음 출력됩니다.

  • out함수에 들어가기 전에 매개 변수에 공식 값이 없음을 의미합니다. 호출 된 함수는이를 초기화해야합니다.매개 변수가 사라집니다.

그것을 보는 나의 마음에 드는 방법은 여기있다 :ref변수를 참조로 전달하는 것입니다.out보조를 선언하는 것입니다.반환 값함수에 대한. 다음과 같이 작성할 수 있습니다.

// This is not C#
public (bool, string) GetWebThing(string name, ref Buffer paramBuffer);

// This is C#
public bool GetWebThing(string name, ref Buffer paramBuffer, out string actualUrl);

각 대안의 효과에 대한 자세한 목록은 다음과 같습니다.

메소드를 호출하기 전에 :

ref: 호출자는 호출 된 메소드에 매개 변수를 전달하기 전에 매개 변수의 값을 설정해야합니다.

out: 호출자 메소드는 메소드를 호출하기 전에 인수의 값을 설정할 필요가 없습니다. 가장 가능성이 높습니다. 사실, 현재 값은 버려집니다.

통화 중 :

ref: 호출 된 메소드는 언제든지 인수를 읽을 수 있습니다.

out: 호출 된 메소드는 매개 변수를 읽기 전에 매개 변수를 초기화해야합니다.

원격 통화 :

ref: 현재 값이 원격 호출로 정렬됩니다. 추가 성능 비용.

out: 원격 호출에 아무 것도 전달되지 않습니다. 빨리.

기술적으로 말해서, 당신은 항상ref대신에out, 그러나out인수의 의미에 대해보다 정확하게 설명 할 수 있으며 때로는 훨씬 효율적일 수 있습니다.


15

OUT의 예 : 변수는 메소드로 들어가서 초기화 된 값을 가져옵니다. 나중에 동일한 값이 main 메소드에 리턴됩니다.

namespace outreftry
{
    class outref
    {
        static void Main(string[] args)
        {
            yyy a = new yyy(); ;

            // u can try giving int i=100 but is useless as that value is not passed into
            // the method. Only variable goes into the method and gets changed its
            // value and comes out. 
            int i; 

            a.abc(out i);

            System.Console.WriteLine(i);
        }
    }
    class yyy
    {

        public void abc(out int i)
        {

            i = 10;

        }

    }
}

산출:

10

=============================================================================

Ref 예제 : 변수는 메소드로 들어가기 전에 초기화되어야합니다. 나중에 동일한 값이나 수정 된 값이 main 메소드로 리턴됩니다.

namespace outreftry
{
    class outref
    {
        static void Main(string[] args)
        {
            yyy a = new yyy(); ;

            int i = 0;

            a.abc(ref i);

            System.Console.WriteLine(i);
        }
    }
    class yyy
    {

        public void abc(ref int i)
        {
            System.Console.WriteLine(i);
            i = 10;

        }

    }
}

산출:

    0
    10

===================

희망은 지금 분명하다.


9

  • 에이ref변수는 변수를 전달하기 전에 초기화해야합니다.
  • out함수 구현에서 변수를 설정해야합니다.
  • out매개 변수는 추가 리턴 변수 (입력이 아님)로 생각할 수 있습니다.
  • ref매개 변수는 입력 변수와 출력 변수로 생각할 수 있습니다.


9

참조 및 출력 매개 변수 :

그만큼out그리고ref매개 변수는 메서드의 인수로 전달하는 동일한 변수의 값을 반환하는 데 사용됩니다. 이 두 매개 변수는 메서드가 둘 이상의 값을 반환해야하는 경우 매우 유용합니다.

Calee 메서드 본문에서 out 매개 변수에 값을 할당해야합니다. 그렇지 않으면 메서드가 컴파일되지 않습니다.


참조 매개 변수 :메서드에 전달하기 전에 초기화해야합니다.   그만큼ref키워드는 메소드 매개 변수에서 동일한 메소드의 입력 매개 변수로 전달 된 동일한 변수를 참조하게합니다. 변수를 변경하면 변수에 반영됩니다.

int sampleData = 0; 
sampleMethod(ref sampleData);

Ex의 Ref 매개 변수

public static void Main() 
{ 
 int i = 3; // Variable need to be initialized 
 sampleMethod(ref i );  
}

public static void sampleMethod(ref int sampleData) 
{ 
 sampleData++; 
} 

출력 매개 변수 :메소드에 전달하기 전에 초기화 할 필요는 없습니다.   그만큼out매개 변수는 메서드의 매개 변수로 전달 된 동일한 변수의 값을 반환하는 데 사용할 수 있습니다. 매개 변수에 대한 변경 사항은 변수에 반영됩니다.

 int sampleData; 
 sampleMethod(out sampleData);

Ex of Out 매개 변수

public static void Main() 
{ 
 int i, j; // Variable need not be initialized 
 sampleMethod(out i, out j); 
} 
public static int sampleMethod(out int sampleData1, out int sampleData2) 
{ 
 sampleData1 = 10; 
 sampleData2 = 20; 
 return 0; 
} 


6

아웃:

C #에서는 메서드가 하나의 값만 반환 할 수 있습니다. 하나 이상의 값을 반환하려면 out 키워드를 사용할 수 있습니다. out 변경자는 참조로 리턴합니다. 가장 간단한 대답은 메서드에서 값을 가져 오는 데 "out"이라는 키워드가 사용된다는 것입니다.

  • 호출 함수에서 값을 초기화 할 필요는 없습니다.
  • 호출 된 함수에 값을 지정해야합니다. 그렇지 않으면 컴파일러에서 오류를보고합니다.

심판 :

C #에서는 int, float, double 등과 같은 값 형식을 메서드 매개 변수의 인수로 전달하면 값에 의해 전달됩니다. 따라서 매개 변수 값을 수정하면 메서드 호출의 인수에 영향을 미치지 않습니다. 그러나 "ref"키워드로 매개 변수를 표시하면 실제 변수에 반영됩니다.

  • 함수를 호출하기 전에 변수를 초기화해야합니다.
  • 메소드의 ref 매개 변수에 값을 지정하는 것은 필수 사항이 아닙니다. 값을 변경하지 않으면 "ref"로 표시 할 필요가 있습니까?


4

Ref 매개 변수는 함수에서 설정하지 않아도되지만 out 매개 변수는 함수를 종료하기 전에 값에 바인딩해야합니다. 변수는 초기화되지 않고 함수로 전달 될 수도 있습니다.


4

out매개 변수가 출력 매개 변수임을 지정합니다. 즉, 매개 변수가 메서드에서 명시 적으로 설정 될 때까지 값을 갖지 않습니다.

ref값이 값을 가지며 값은 메소드 내에서 변경할 수있는 참조임을 지정합니다.


1

out매개 변수는 호출 된 메소드에 의해 초기화되며,ref매개 변수는 메서드를 호출하기 전에 초기화됩니다. 따라서,out매개 변수는 2 차 리턴 값을 얻고 자 할 때 사용되며,ref매개 변수가 값을 가져 오는 데 사용됩니다.잠재적으로 그 값 (2 차적으로 주 리턴 값)에 대한 변경을 리턴합니다.


1

ref 키워드는 참조로 값을 전달하는 데 사용됩니다. (전달 된 값이 값 유형 또는 참조 유형이되는 것을 배제하지 않음). out 키워드로 지정된 출력 매개 변수는 메서드에서 값을 반환하기위한 것입니다.

코드의 주요 차이점 중 하나는 메서드 내에서 출력 매개 변수의 값을 설정해야한다는 것입니다. 이것은 ref 매개 변수의 경우가 아닙니다.

자세한 내용은http://www.blackwasp.co.uk/CSharpMethodParameters.aspx


1

out매개 변수는ref매개 변수가있는 특수 문자Out()속성이 추가되었습니다. C #메서드에 대한 매개 변수가로 선언 된 경우out, 컴파일러는 매개 변수를 읽을 수 있고 메서드가 반환되기 전에 매개 변수를 작성해야합니다. C #이 매개 변수에Out()속성을 사용하는 경우 컴파일러는 "정의되지 않은 변수"오류를보고할지 여부를 결정하기 위해 변수를 메서드를 호출하기 전에 즉시 작성합니다. 다른 .net 언어가 동일한 의미를 붙이지 않기 때문에Out()속성을 사용하여 루틴을 호출 할 수 있습니다.out매개 변수는 문제의 변수에 영향을주지 않습니다. 변수가out매개 변수가 확실히 할당되기 전에 C #컴파일러는 사용되기 전에 어느 지점에서 지워지는 코드를 생성하지만 그러한 변수가 범위를 벗어나 다시 입력하면 다시 지워질 것이라고 보장 할 수 없습니다.


0

ref는 아마도 기존 객체를 수정하려고하기 때문에 아마도 null에 질식 할 것입니다. out은 새로운 객체를 반환하기 때문에 null을 기대합니다.


  • Foo (ref null)는 컴파일되지 않지만 string bar는 null입니다. 푸 (참조 표시 줄); 괜찮습니다. - James Curran
  • null 상수에 질식? James Curran은 ref 인수에 상수를 전달할 수 없습니다. - Andrei Rînea
  • null 상수를 의미하지 않았습니다. null 값을 가진 변수를 의미했습니다. - Joel Coehoorn

0

out과 ref는 out 변수가 심연으로 보내기 전에 초기화 될 필요가 없다는 예외와 완전히 동일합니다. 나는 그렇게 똑똑하지 않습니다, 나는 MSDN 라이브러리에서 그것을 cribbed :).

그러나 사용법을 더 명확히하기 위해 수정 자의 의미는 코드에서 해당 변수의 참조를 변경하면 out 및 ref로 인해 호출 변수가 참조를 변경하게된다는 것입니다. 아래 코드에서 ceo 변수는 doStuff 호출에서 반환 된 newGuy에 대한 참조가됩니다. 참조가 아닌 경우 참조가 변경되지 않습니다.

private void newEmployee()
{
    Person ceo = Person.FindCEO();
    doStuff(ref ceo);
}

private void doStuff(ref Person employee)
{
    Person newGuy = new Person();
    employee = newGuy;
}


0

밖으로 및 참조 Paramerter C #좋은 예가있다.

요약 된 기본 차이점은out매개 변수는 전달 될 때 초기화 될 필요가 없으며 ref 매개 변수는 초기화됩니다.


0

출력 매개 변수메소드 선언에서 선언 된 경우, 메소드 본문은 리턴하기 전에 out 변수에 값을 지정해야합니다. 따라서 out 매개 변수가 반환되기 전에 값을 할당하는 것은 호출 된 메서드의 책임입니다.

참조 매개 변수이 메소드에서 선언되면 메소드를 호출하는 동안 전달되는 인수는 값을 할당해야합니다. 메소드를 호출하기 전에 ref 인자에 값을 할당하는 것은 호출자의 책임입니다.


0

그들은 미묘하게 다릅니다.

out매개 변수는 메서드에 전달되기 전에 호출 수신자에 의해 초기화 될 필요가 없습니다. 따라서,out매개 변수

  • 값을 지정하기 전에 매개 변수를 읽을 수 없습니다.
  • 반환하기 전에 값을 지정해야합니다.

이것은 이전 값과 상관없이 인수를 겹쳐 써야하는 메소드에 사용됩니다.


에이ref매개 변수는 메서드에 전달하기 전에 호출 수신자에 의해 초기화되어야합니다. 따라서,ref매개 변수

  • 값을 할당하기 전에 검사 할 수 있음
  • 원래 값을 그대로 되돌릴 수 있음

이것은 그 값을 검사 (예 : 검사)해야만하고 검증 (validate) 또는 정상화 (normalize)해야하는 메소드에 사용됩니다.


0

out은 C #7에 새로운 succint 구문을 추가했습니다.https://docs.microsoft.com/en-us/dotnet/articles/csharp/whats-new/csharp-7#more-expression-bodied-membersC #7 튜플 확장은 ref 및 out IMHO를 사용하는 것보다 더 우아한 선택입니다.

연결된 질문


관련된 질문

최근 질문