C # 4.0 선택적 out / ref 인수


212

C # 4.0은 선택적 out또는 ref인수를 허용합니까 ?


2
C ++은 효과적으로 "out"매개 변수를 가지고있다. 주소 인수는 null로 초기화 될 수 있으며 포인터가 널이 아닌 경우에만 이러한 리턴 구조를 채우는 라이브러리 코드를 작성하는 것이 일반적이다. 그것은 C API에서 "선택적 인수"에 null을 사용하는 관용구입니다.
— Andy Dent

53
@Ed와 모두 : 왜 이것이 말이되지 않습니까? 함수가 "out"을 통해 값을 "반환"하면 강제로 받아들이고 싶지 않습니다. 이제 기술적 인 이유로 컴파일러가 여전히 무언가를 전달해야한다는 것을 알고 있지만 내 뒤에서 나를 위해 더미 로컬을 만들 수없는 이유는 없습니다.
— Roman Starkov

5
사물이 어떻게 구현되는지 또는 선택적 매개 변수가 무엇인지에 대한 관점에서 말이 안될 수도 있습니다. 그러나 롬 킨스가 말했듯이, "선택적 인수"를 갖는 것이 정말 좋을 것입니다. CLR이 아닌 영어로 해석하면 합리적이고 IMO에서는 바람직합니다.
— Adam Tolley

9
C #은 그렇지 않지만 VB.NET은 그렇지 않습니다.
— Jason

5
그러나 이것은 선택의 여지가 있지만, 선택적인 논쟁에 대한 나의지지를 언급 ​​할 수는 없다. 나는 null기본 설정 ( PHP에서 온 것)을 통해 참조를 통해 선택적 인수에 상당히 익숙해졌습니다. 어쨌든 null인수를 채우는 테스트 ( 친숙한 사람들은 생각합니다preg_match() ) 어쨌든 기술적 인 관점에서 현재 이해 할 수 있습니다. 불가능하다. PHP와 C #은 비교할 수 없지만 여전히 " 좋은 "도구가 될 것이다.
— Dan Lugg

답변:


93

이미 언급했듯이 이것은 단순히 허용되지 않으며 매우 의미가 있다고 생각합니다. 그러나 자세한 내용을 추가하려면 C # 4.0 Specification 섹션 21.1 의 인용문을 참조하십시오 .

생성자, 메서드, 인덱서 및 대리자 형식의 형식 매개 변수는 선택적으로 선언 될 수 있습니다.

고정 매개 변수 :
    속성 opt 매개 변수 수정 자 opt 유형 식별자 default-argument opt
default-argument :
    = expression

  • 고정 매개 변수 A를 기본 인수는 입니다 선택적 매개 변수 반면, 고정 매개 변수 없이 기본 인수는 A는 필수 매개 변수 .
  • formal-parameter-list 의 선택적 매개 변수 뒤에 필수 매개 변수가 표시 될 수 없습니다 .
  • ref또는 out매개 변수는 사용할 수 없습니다 기본 인수를 .

또는 ref / out 매개 변수를 사용하여 과부하를 작성할 수 있습니다. 네, 두 개의 함수 정의가있을 것입니다. 그러나 다음에 달성 할 것입니다
— Chad

201

아니.

해결 방법은 out / ref 매개 변수 가없고 현재 메서드를 호출하는 다른 메서드로 오버로드하는 것 입니다.

public bool SomeMethod(out string input)
{
    ...
}

// new overload
public bool SomeMethod()
{
    string temp;
    return SomeMethod(out temp);
}

업데이트 : C # 7.0 인 경우 다음을 단순화 할 수 있습니다.

// new overload
public bool SomeMethod()
{
    return SomeMethod(out _);    // declare out as an inline discard variable
}

(이 점을 지적 해준 @Oskar / @Reiner에게 감사합니다.)


6
임시 / 더미를 선언하는 것보다 더 우아한 솔루션에 대한 아이디어가 있습니까?
— 루이스리스

20
그게 뭐가 우아하지 않습니까? 나에게 완벽하게 보인다.
— Neutrino

27
어쩌면 괜찮지 만 우아한 것은 다른 리그에 있습니다. 더 나은 해결책이 없다고해서 이것이 법령에 의해 최첨단임을 의미하는 것은 아닙니다.
— o0 '.

7
@ o0 '을 누르고 있습니다. C # 7.0에서는 다음을 수행 할 수 있습니다 return SomeMethod(out string temp).. 자세한 내용은 여기를 참조하십시오 : blogs.msdn.microsoft.com/dotnet/2016/08/24/…
— Oskar

7
C # 7.0에서는 다음과 같은 임시 쓰기 전용 변수를 사용할 수 있습니다.return SomeMethod(out _);
— Reiner

64

아니요, 그러나 다른 좋은 대안은 다음과 같이 메소드가 선택적 매개 변수에 일반 템플리트 클래스를 사용하도록하는 것입니다.

public class OptionalOut<Type>
{
    public Type Result { get; set; }
}

그런 다음 다음과 같이 사용할 수 있습니다.

public string foo(string value, OptionalOut<int> outResult = null)
{
    // .. do something

    if (outResult != null) {
        outResult.Result = 100;
    }

    return value;
}

public void bar ()
{
    string str = "bar";

    string result;
    OptionalOut<int> optional = new OptionalOut<int> ();

    // example: call without the optional out parameter
    result = foo (str);
    Console.WriteLine ("Output was {0} with no optional value used", result);

    // example: call it with optional parameter
    result = foo (str, optional);
    Console.WriteLine ("Output was {0} with optional value of {1}", result, optional.Result);

    // example: call it with named optional parameter
    foo (str, outResult: optional);
    Console.WriteLine ("Output was {0} with optional value of {1}", result, optional.Result);
}

19
매우 합리적인 해결책이지만, 알아야 할 한 가지는 컴파일러가 메소드를 종료하기 전에 out 매개 변수를 지정해야한다는 요구 사항을 강제하지 않는다는 것입니다.
— Ken Smith

2
마음에 들지만 새 클래스를 만들고 싶지 않으면 단일 요소 배열을 전달하여 시뮬레이션 할 수 있습니다.
— zumalifeguard

30

실제로 C #에서 허용하는 방법이 있습니다. 이것은 C ++로 돌아가고 C #의 멋진 Object-Oriented 구조를 위반합니다.

이 방법을주의해서 사용하십시오!

선택적 매개 변수를 사용하여 함수를 선언하고 작성하는 방법은 다음과 같습니다.

unsafe public void OptionalOutParameter(int* pOutParam = null)
{
    int lInteger = 5;
    // If the parameter is NULL, the caller doesn't care about this value.
    if (pOutParam != null) 
    { 
        // If it isn't null, the caller has provided the address of an integer.
        *pOutParam = lInteger; // Dereference the pointer and assign the return value.
    }
}

그런 다음 다음과 같이 함수를 호출하십시오.

unsafe { OptionalOutParameter(); } // does nothing
int MyInteger = 0;
unsafe { OptionalOutParameter(&MyInteger); } // pass in the address of MyInteger.

이를 컴파일하려면 프로젝트 옵션에서 안전하지 않은 코드를 활성화해야합니다. 이것은 일반적으로 사용해서는 안되는 매우 해킹 된 솔루션이지만 이상한 이상한 신비한 관리 영감을 얻은 결정에 정말로 C #에서 선택적 매개 변수가 필요하다면 그렇게 할 수 있습니다.


6

ICYMI는 : 열거 된 C # 7.0의 새로운 기능에 포함 된 여기에 , "폐기"가 지금의 형태 _의 매개 변수 아웃으로 허용, 당신은 당신이 걱정하지 않는 매개 변수를 무시하도록하려면 :

p.GetCoordinates(out var x, out _); // I only care about x

PS "out var x"부분과 혼동되는 경우 링크에서 "Out Variables"에 관한 새로운 기능을 읽으십시오.


_ 또는 * "p.GetCoordinates (out int x, out *); // x에만 관심이 있습니다"
— Onur Topal

이전 버전의 문서를보고있는 것 같습니다.
— Onur Topal

2

아니요, 대신 대리인 (예 :)을 사용할 수 있습니다 Action.

선택적 매개 변수를 원한다고 생각하는 상황에 직면했을 때 Robin R의 대답에서 부분적으로 영감을 얻은 대신 Action대리자 를 사용했습니다 . Action<int>차이점과 유사성을 보여주기 위해 그의 예제 코드를 빌려 사용하도록 수정했습니다 .

public string foo(string value, Action<int> outResult = null)
{
    // .. do something

    outResult?.Invoke(100);

    return value;
}

public void bar ()
{
    string str = "bar";

    string result;
    int optional = 0;

    // example: call without the optional out parameter
    result = foo (str);
    Console.WriteLine ("Output was {0} with no optional value used", result);

    // example: call it with optional parameter
    result = foo (str, x => optional = x);
    Console.WriteLine ("Output was {0} with optional value of {1}", result, optional);

    // example: call it with named optional parameter
    foo (str, outResult: x => optional = x);
    Console.WriteLine ("Output was {0} with optional value of {1}", result, optional);
}

이는 선택적 변수가 소스에 일반 int로 표시되는 이점이 있습니다 (컴파일러는 사용자 정의 클래스로 명시 적으로 래핑하지 않고 클로저 클래스로 래핑합니다).

컴파일러는 Action함수 호출이 종료되기 전에 의지가 호출 될 것이라고 가정 할 수 없으므로 변수를 명시 적으로 초기화해야합니다 .

모든 유스 케이스에 적합하지는 않지만 실제 유스 케이스 (단위 테스트를위한 데이터를 제공하는 함수 및 새로운 단위 테스트가 리턴 값에 존재하지 않는 일부 내부 상태에 액세스 해야하는 기능)에서는 잘 작동했습니다.


0

out 매개 변수없이 오버로드 된 메서드를 사용하여 C # 6.0 이하의 out 매개 변수가있는 메서드를 호출하십시오. C # 4.0에 선택적 출력 매개 변수가 있는지 여부를 구체적으로 물었을 때 .NET Core 용 C # 7.0이이 스레드에 대한 정답 인 이유를 잘 모르겠습니다. 내 대답은 아니오 야!


-2

이건 어때?

public bool OptionalOutParamMethod([Optional] ref string pOutParam)
{
    return true;
}

여전히 C #에서 매개 변수로 값을 전달해야하지만 선택적 ref 매개 변수입니다.


8
“여전히 C #에서 매개 변수에 값을 전달해야합니다.”... 이것은 선택 사항이 아닙니다.
— Arturo Torres Sánchez

C #은 [Optional]주석을 무시합니다 . 도움이되지 않습니다.
— ToolmakerSteve

-4
void foo(ref int? n)
{
    return null;
}

1
모든 사람들이 개념을 쉽게 이해할 수 있도록 코드에 대한 설명을 추가하십시오
— techspider

1
이 코드는 질문에 대답 할 수 있지만, 질문에 대한 이유 및 / 또는 방법 에 대한 추가 컨텍스트를 제공 하면 장기적인 가치가 크게 향상됩니다. 제발 편집 약간의 설명을 추가 할 답변을.
— Toby Speight

2
메소드에 void 리턴 유형이 있으므로 구문 오류가 발생합니다. 또한 질문에 대답하지 않습니다.
— Nathan Montez
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.