out 인수를 명시 적으로 버리는 방법은 무엇입니까?


99

전화를 겁니다.

myResult = MakeMyCall(inputParams, out messages);

하지만 사실은 메시지에 신경 쓰지 않습니다. 입력 매개 변수라면 신경 쓰지 않고 그냥 null을 전달합니다. 그것이 반환이라면 나는 신경 쓰지 않았을뿐입니다.

out과 비슷한 작업을 수행 할 수있는 방법이 있습니까? 아니면 무시할 변수를 선언해야합니까?


여기에 비슷한 질문 : stackoverflow.com/questions/2870544/...
덩크


감사! 최신 버전이 아니라는 점이 아쉽습니다.
Andrew Ducker

답변:


99

C # 7.0부터는 매개 변수를 미리 선언하거나 무시하는 것을 피할 수 있습니다.

public void PrintCoordinates(Point p)
{
    p.GetCoordinates(out int x, out int y);
    WriteLine($"({x}, {y})");
}

public void PrintXCoordinate(Point p)
{
    p.GetCoordinates(out int x, out _); // I only care about x
    WriteLine($"{x}");
}

출처 : https://blogs.msdn.microsoft.com/dotnet/2017/03/09/new-features-in-c-7-0/


1
안타깝게도 C # 7 (2017 년 4 월 기준)에는 포함되어 있지 않습니다.
tia apr

2
@tia. 내 답변을 업데이트했습니다. 분명히, 와일드 카드 문자로 변경되었습니다 *_. 너무 오래 걸려서 죄송합니다.
Nolonar

14
그들은 out void구문 에 사용하는 아이디어를 고수해야 했으며 밑줄은 이상한 선택처럼 보입니다.
David Anderson

1
@ DavidAnderson-DCOM 내가 밑줄을 좋아하지는 않지만 과부하 해결을 위해 유형 이름이 필요하다고 생각합니다.
Jonathan Allen

_ = {a value};컴파일 오류없이 함수 호출 뒤에 줄 을 추가 할 수 있기 때문에 여전히 매개 변수를 만드는 것처럼 보입니다 .
Bip901

37

불행히도 당신은 무언가를 설정하기 위해 메서드가 필요하기 때문에 무언가를 전달해야합니다. 따라서 null설정에 필요한 방법이 폭발 할 것이기 때문에 보낼 수 없습니다 .

추악함을 숨기는 한 가지 방법 out은 다음과 같이 매개 변수를 수행하는 다른 메소드로 메소드를 래핑하는 것입니다 .

String Other_MakeMyCall(String inputParams)
{
    String messages;

    return MakeMyCall(inputParams, out messages);
}

그런 다음 필요하지 않은 매개 변수를 조작하지 Other_MakeMyCall않고도 호출 할 수 있습니다 out.


37

무시할 변수를 선언해야합니다. 이것은 TryParse (또는 TryWhatever) 패턴의 경우 가장 일반적으로, 실제 구문 분석 된 값을 신경 쓰지 않고 사용자 입력의 유효성을 테스트하는 데 사용됩니다 (예 : 숫자로 구문 분석 할 수 있습니까?).

질문에서 "dispose"라는 단어를 사용했습니다. 제가 생각하기에 불행한 것입니다.하지만 out 매개 변수가 IDisposable을 구현하는 유형 인 경우 메서드 문서에서 값을받는 것이 허용되지 않는다고 명시 적으로 언급하지 않는 한 Dispose를 호출해야합니다. 소유권. out하지만 일회용 매개 변수 가있는 메서드를 본 적이 없기 때문에 이것이 단지 운이 좋지 않은 단어 선택 이었으면합니다.


실용적인 안티 패턴의 더
Jodrell

11

원래 함수가 다음과 같이 선언 된 경우 :

class C
{
    public Result MakeMyCall(Object arg, out List<String> messages);
}

다음과 같이 확장 메서드를 선언 할 수 있습니다.

static class CExtension
{
    public static Result MakeMyCall(this C obj, Object arg)
    {
        List<String> unused;
        return obj.MakeMyCall(arg, out unused);
    }
}

확장 메서드는 out 매개 변수를 선택적으로 만드는 오버로드처럼 동작합니다.


4

Visual Basic 컴파일러는 더미 변수를 만들어이를 수행합니다. 마이크로 소프트가 좋은 아이디어라고 확신 할 수 있다면 C #으로 할 수 있습니다.


0

클래스가를 messages구현 하는 경우 IDisposable무시해서는 안됩니다. 다음 접근 방식과 같은 것을 고려하십시오 (한동안 C #을 작성하지 않았기 때문에 구문 상 정확하지 않을 수 있음).

using (FooClass messages) {
    myResult = MakeMyCall(inputParams, messages);
}

using블록을 벗어나면 messages자동으로 폐기됩니다.


1
흥미 롭군. 하지만 using 문에서 변수를 초기화 할 필요가 없습니까?
OregonGhost

1
@OregonGhost : 네, 그렇습니다. 그리고 using 문 내에서 변수의 값을 변경해도 삭제 되는 것은 여전히 원래의 값입니다.
Jon Skeet

@JonSkeet 그것은 여전히 ​​폐기 된 원래 가치를
Orkhan Alikhanov

@OrkhanAlikhanov : 컴파일러는 기본적으로 using명령문 시작 부분에서 변수의 복사본을 사용합니다 . 따라서 블록 내에서 해당 변수의 값을 변경해도 삭제되는 객체는 변경되지 않습니다.
Jon Skeet

그건 그렇고, out messages.
Orkhan Alikhanov

0

out 매개 변수에 대한 변수를 전달해야합니다. 전달하기 전에 변수를 초기화 할 필요가 없습니다.

MyMessagesType messages;
myResult = MakeMyCall(inputParams, out messages); 

일반적으로 호출 후 '메시지'를 무시할 수 있습니다. 제한된 시스템 리소스 사용과 같은 이유로 '메시지'를 처리해야하는 경우가 아니면 Dispose ()를 호출해야합니다.

messages.Dispose();

상당한 양의 메모리를 사용할 수 있고 한동안 범위에 남아있을 경우 참조 유형 인 경우 null로 설정하고 값 유형 인 경우 새 기본 인스턴스로 설정해야합니다. 수집기는 메모리를 회수 할 수 있습니다.

messages = null; // Allow GC to reclaim memory for reference type.

messages = new MyMessageType(); // Allow GC to reclaim memory for value type.

0

이 경우에는 Delete 또는 Remove 메서드가없는 ConcurrentDictionary에 대한 일반 확장 메서드를 만들었습니다.

//Remove item from list and ignore reference to removed item
public static void TryRemoveIgnore<K,T>(this ConcurrentDictionary<K,T> dictionary, K key)
{
    T CompletelyIgnored;
    dictionary.TryRemove(key, out CompletelyIgnored);
}

ConcurrentDictionary 인스턴스에서 호출되는 경우 :

ClientList.TryRemoveIgnore(client.ClientId);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.