[c#] 두 값 반환, Tuple vs ‘out’vs ‘struct’

두 개의 값을 반환하는 함수를 고려하십시오. 우리는 쓸 수있다:

// Using out:
string MyFunction(string input, out int count)

// Using Tuple class:
Tuple<string, int> MyFunction(string input)

// Using struct:
MyStruct MyFunction(string input)

어떤 것이 모범 사례이며 그 이유는 무엇입니까?



답변

그들은 각각 장단점이 있습니다.

Out 매개 변수는 빠르고 저렴하지만 변수를 전달하고 변이에 의존해야합니다. LINQ에서 out 매개 변수를 올바르게 사용하는 것은 거의 불가능합니다.

튜플은 가비지 수집에 압력을 가하며 자체 문서화되지 않습니다. “Item1″은 그다지 설명 적이 지 않습니다.

사용자 지정 구조체는 크면 복사 속도가 느릴 수 있지만 자체 문서화되고 작 으면 효율적입니다. 그러나 사소한 용도로 전체 사용자 정의 구조체를 정의하는 것도 고통입니다.

나는 사용자 정의 구조체 솔루션이 다른 모든 것들이 동일하다는 경향이 있습니다. 더 좋은 방법 은 하나의 값만 반환하는 함수만드는 것 입니다. 처음에 두 개의 값을 반환하는 이유는 무엇입니까?

업데이트 :이 기사가 작성된 후 6 년 후에 출시 된 C # 7의 튜플은 값 유형이므로 수집 압력을 유발할 가능성이 적습니다.


답변

이전 답변에 추가하면 C # 7은 값 유형 튜플을 제공합니다. System.Tuple 참조 유형과 향상된 의미 체계를 제공합니다.

이름을 지정하지 않고 다음 .Item*구문을 사용할 수 있습니다 .

(string, string, int) getPerson()
{
    return ("John", "Doe", 42);
}

var person = getPerson();
person.Item1; //John
person.Item2; //Doe
person.Item3;   //42

하지만이 새로운 기능에 대해 정말 강력한 것은 튜플에 이름을 지정할 수 있다는 것입니다. 따라서 위의 내용을 다음과 같이 다시 작성할 수 있습니다.

(string FirstName, string LastName, int Age) getPerson()
{
    return ("John", "Doe", 42);
}

var person = getPerson();
person.FirstName; //John
person.LastName; //Doe
person.Age;   //42

구조 분해도 지원됩니다.

(string firstName, string lastName, int age) = getPerson()


답변

대답은 함수가하는 일의 의미와 두 값 사이의 관계에 달려 있다고 생각합니다.

예를 들어, TryParse메서드 out는 파싱 된 값을 받아들이는 매개 변수를 사용 bool하고 파싱이 성공했는지 여부를 나타내는 a 를 반환합니다 . 두 값은 실제로는 함께 속하지 않으므로 의미 상 더 의미가 있으며 out매개 변수 를 사용하는 코드의 의도를 더 쉽게 읽을 수 있습니다 .

그러나 함수가 화면에있는 일부 개체의 X / Y 좌표를 반환하는 경우 두 값이 의미 상 함께 속하므로 struct.

나는 개인적으로 tuple멤버를 검색하는 어색한 구문 때문에 외부 코드에 표시되는 모든 것에 대해 사용하는 것을 피할 것입니다.


답변

두 번째 방법에서는 Tuple 클래스를 생성하고 객체를 생성 한 다음 여기에 값을 추가해야하므로 Out 매개 변수를 사용하는 방법을 사용하겠습니다.이 작업은 out 매개 변수에서 값을 반환하는 것보다 비용이 많이 드는 작업이라고 생각합니다. 튜플 클래스에서 여러 값을 반환하려는 경우 (실제로 하나의 매개 변수를 반환하여 수행 할 수 없음) 두 번째 방법을 사용합니다.


답변

구조체 대신 사용자 지정 클래스가있는 옵션을 하나 더 언급하지 않았습니다. 데이터에 함수에 의해 작동 될 수있는 관련 의미가 있거나 인스턴스 크기가 충분히 큰 경우 (일반적으로> 16 바이트) 사용자 지정 클래스가 선호 될 수 있습니다. 포인터에 대한 연관성과 참조 유형의 작동 방식을 이해해야하므로 공용 API에서 “out”을 사용하지 않는 것이 좋습니다.

https://msdn.microsoft.com/en-us/library/ms182131.aspx

튜플은 내부 사용에는 좋지만 공용 API에서는 사용이 어색합니다. 그래서 내 투표는 공용 API에 대한 구조체와 클래스 사이에 있습니다.


답변

“모범 사례”는 없습니다. 그것은 당신이 편안하고 당신의 상황에서 가장 잘 작동하는 것입니다. 이것과 일치하는 한 게시 한 솔루션에 문제가 없습니다.


답변