두 개의 값을 반환하는 함수를 고려하십시오. 우리는 쓸 수있다:
// Using out:
string MyFunction(string input, out int count)
// Using Tuple class:
Tuple<string, int> MyFunction(string input)
// Using struct:
MyStruct MyFunction(string input)
어떤 것이 모범 사례이며 그 이유는 무엇입니까?
두 개의 값을 반환하는 함수를 고려하십시오. 우리는 쓸 수있다:
// Using out:
string MyFunction(string input, out int count)
// Using Tuple class:
Tuple<string, int> MyFunction(string input)
// Using struct:
MyStruct MyFunction(string input)
어떤 것이 모범 사례이며 그 이유는 무엇입니까?
struct
으로 Eric
언급했다.
답변:
그들은 각각 장단점이 있습니다.
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
멤버를 검색하는 어색한 구문 때문에 외부 코드에 표시되는 모든 것에 대해 사용하는 것을 피할 것입니다.
out
매개 변수를 떠날 수있을 때 더 적절한 whit 참조 유형 null
입니다. nullable 불변 유형이 몇 가지 있습니다.
try
공변 인터페이스에서 작동 하는 유일한 패턴은 T TryGetValue(whatever, out bool success)
; 그 방법은 인터페이스를 허용 한 것 IReadableMap<in TKey, out TValue> : IReadableMap<out TValue>
, 그리고 인스턴스를지도하고자하는 코드하자 Animal
의 인스턴스에 Car
받아 Dictionary<Cat, ToyotaCar>
[사용하여 TryGetValue<TKey>(TKey key, out bool success)
. 매개 변수 TValue
로 사용되는 경우 이러한 분산은 불가능합니다 ref
.
구조체 대신 사용자 지정 클래스가있는 옵션을 하나 더 언급하지 않았습니다. 데이터에 함수에 의해 작동 될 수있는 관련 의미가 있거나 인스턴스 크기가 충분히 큰 경우 (일반적으로> 16 바이트) 사용자 지정 클래스가 선호 될 수 있습니다. 포인터에 대한 연관성과 참조 유형의 작동 방식을 이해해야하므로 공용 API에서 "out"을 사용하지 않는 것이 좋습니다.
https://msdn.microsoft.com/en-us/library/ms182131.aspx
튜플은 내부 사용에는 좋지만 공용 API에서는 사용이 어색합니다. 그래서 내 투표는 공용 API에 대한 구조체와 클래스 사이에 있습니다.