[C#] 반환 값 또는 출력 매개 변수 중 어느 것이 더 낫습니까?

메소드에서 값을 얻으려면 다음과 같이 반환 값을 사용할 수 있습니다.

public int GetValue(); 

또는:

public void GetValue(out int x);

나는 그들 사이의 차이점을 실제로 이해하지 못하므로 어느 것이 더 좋은지 모릅니다. 설명 해줄 수 있습니까?

감사합니다.



답변

메서드에 반환 할 다른 항목이없는 경우 반환 값은 거의 항상 올바른 선택입니다. (사실, 난 것 어떤 경우 생각할 수 없다 이제까지 보이드 방법을 원하는 out나는 선택의 여지가있는 경우, 매개 변수입니다. 7의 C # Deconstruct언어 지원 해체하는 방법이 규칙에 매우, 매우 드문 예외로 작용 .)

다른 것 외에도 호출자가 변수를 별도로 선언하지 않아도됩니다.

int foo;
GetValue(out foo);

vs

int foo = GetValue();

Out 값은 다음과 같이 메소드 체인을 방지합니다.

Console.WriteLine(GetValue().ToString("g"));

(실제로, 이는 속성 설정 기의 문제 중 하나이기도하므로 빌더 패턴이 빌더를 리턴하는 메소드를 사용하는 이유입니다 (예 🙂 myStringBuilder.Append(xxx).Append(yyy).

또한 출력 매개 변수는 리플렉션과 함께 사용하기가 약간 어렵고 일반적으로 테스트도 어렵게 만듭니다. (일반적으로 매개 변수보다 반환 값을 쉽게 조롱하기 위해 더 많은 노력을 기울입니다). 기본적으로 그들이 더 쉽게 만들 수 있다고 생각할 수있는 것은 없습니다 …

반환 값 FTW.

편집 : 무슨 일인지에 관해서 …

당신이 “밖으로”매개 변수에 인수를 전달하면 기본적으로, 변수에 전달합니다. (배열 요소도 변수로 분류됩니다.) 호출하는 메소드에는 매개 변수의 스택에 “새”변수가 없습니다. 변수에 저장을 위해 사용합니다. 변수의 모든 변경 사항이 즉시 표시됩니다. 차이점을 보여주는 예는 다음과 같습니다.

using System;

class Test
{
    static int value;

    static void ShowValue(string description)
    {
        Console.WriteLine(description + value);
    }

    static void Main()
    {
        Console.WriteLine("Return value test...");
        value = 5;
        value = ReturnValue();
        ShowValue("Value after ReturnValue(): ");

        value = 5;
        Console.WriteLine("Out parameter test...");
        OutParameter(out value);
        ShowValue("Value after OutParameter(): ");
    }

    static int ReturnValue()
    {
        ShowValue("ReturnValue (pre): ");
        int tmp = 10;
        ShowValue("ReturnValue (post): ");
        return tmp;
    }

    static void OutParameter(out int tmp)
    {
        ShowValue("OutParameter (pre): ");
        tmp = 10;
        ShowValue("OutParameter (post): ");
    }
}

결과 :

Return value test...
ReturnValue (pre): 5
ReturnValue (post): 5
Value after ReturnValue(): 10
Out parameter test...
OutParameter (pre): 5
OutParameter (post): 10
Value after OutParameter(): 10

차이점은 “포스트”단계에서, 즉 로컬 변수 또는 매개 변수가 변경된 후입니다. ReturnValue 테스트에서는 정적 value변수와 아무런 차이가 없습니다 . OutParameter 테스트에서 value변수는 행에 의해 변경됩니다tmp = 10;


답변

더 나은 방법은 특정 상황에 따라 다릅니다. 존재 하는 이유 중 하나out하나의 메소드 호출에서 여러 값을 쉽게 리턴하기위한 것입니다.

public int ReturnMultiple(int input, out int output1, out int output2)
{
    output1 = input + 1;
    output2 = input + 2;

    return input;
}

따라서 하나는 다른 것보다 더 나은 것은 아닙니다. 그러나 일반적으로 위와 같은 상황이 아닌 한 간단한 반환을 사용하려고합니다.

편집 :
키워드가 존재하는 이유 중 하나를 보여주는 샘플입니다. 위의 방법은 최선의 방법으로 간주되지 않습니다.


답변

일반적으로 out 매개 변수보다 반환 값을 선호해야합니다. 두 가지 일을 해야하는 코드를 작성하는 것을 발견하면 아웃 매개 변수는 필요한 악입니다. 이에 대한 좋은 예는 Try 패턴입니다 (예 : Int32.TryParse).

두 메소드의 호출자가해야 할 일을 고려해 봅시다. 첫 번째 예를 위해 이것을 쓸 수 있습니다 …

int foo = GetValue();

변수를 선언하고 한 줄로 메소드를 통해 할당 할 수 있습니다. 두 번째 예에서는 다음과 같습니다.

int foo;
GetValue(out foo);

이제 변수를 미리 선언하고 두 줄로 코드를 작성해야합니다.

최신 정보

이러한 유형의 질문을 할 때 살펴 봐야 할 곳은 .NET Framework 디자인 지침입니다. 책 버전이있는 경우이 주제 (184-185 페이지)에서 Anders Hejlsberg와 다른 사람들이 주석을 볼 수 있지만 온라인 버전은 여기에 있습니다 …

http://msdn.microsoft.com/en-us/library/ms182131(VS.80).aspx

API에서 두 가지를 반환 해야하는 경우 struct / class로 래핑하는 것이 out param보다 낫습니다.


답변

out아직 언급되지 않은 매개 변수 를 사용하는 한 가지 이유가 있습니다 . 호출 메소드가이를 수신해야합니다. 메소드가 호출자가 버려서는 안되는 값을 생성 out하면 호출자가 구체적으로 수락 하도록 강제합니다.

 Method1();  // Return values can be discard quite easily, even accidentally

 int  resultCode;
 Method2(out resultCode);  // Out params are a little harder to ignore

물론 호출자 는 매개 변수 의 을 여전히 무시할 수 out있지만주의를 기울였습니다.

이것은 드문 필요입니다. 더 자주, 실제 문제에 대한 예외를 사용하거나 “FYI”에 대한 상태 정보가있는 오브젝트를 리턴해야하지만 이것이 중요한 상황이있을 수 있습니다.


답변

주로 선호

나는 반품을 선호하며 여러 반품이 있으면 결과 DTO에 포장 할 수 있습니다

public class Result{
  public Person Person {get;set;}
  public int Sum {get;set;}
}


답변

하나의 반환 값만 가질 수있는 반면 여러 개의 출력 매개 변수를 가질 수 있습니다.

이 경우 매개 변수 만 고려하면됩니다.

그러나 메소드에서 둘 이상의 매개 변수를 반환 해야하는 경우 OO 접근 방식에서 반환되는 것을 보고이 매개 변수를 사용하여 객체 또는 구조체를 반환하는 것이 더 나은지 고려할 수 있습니다. 따라서 다시 반환 값으로 돌아갑니다.


답변

거의 항상 반환 값을 사용해야합니다. ‘ out‘매개 변수는 많은 API, 구성 성 등에 약간의 마찰을 일으 킵니다.

가장 주목할만한 예외는 TryParse패턴 과 같이 여러 값을 반환하려는 경우입니다 (.Net Framework에는 4.0까지 튜플이 없음) .