.Net 4.0에서 Tuple을 사용할 수있는 실제 예?


97

.Net 4에 도입 된 Tuple을 보았지만 어디에 사용할 수 있는지 상상할 수 없습니다. 우리는 항상 Custom 클래스 또는 Struct를 만들 수 있습니다.


13
이 주제가 매우 오래되었다는 점을 주목하는 것이 좋습니다. C # 7 에서 무슨 일이 일어 났는지보세요 !
maf-soft

답변:


83

그게 요점 입니다. 항상 사용자 정의 클래스 나 구조체를 만들지 않는 것이 더 편리 합니다. 이 같은 개선 Action또는 Func...이 유형을 직접 만들 수 있지만 그들이 프레임 워크에 존재하는 것이 편리합니다.


5
에서 지적 아마 가치가 MSDN : ".이 형식의 모든 공용 정적 멤버는 스레드 안전 인스턴스 멤버는 스레드 안전 보장되지 않습니다. "
마 보르

글쎄, 아마도 언어 디자이너가 사용자 정의 유형을 즉석에서 쉽게 만들 수 있도록 만들었어야했을까요? 그래서 우리는 또 다른 것을 도입하는 대신 동일한 구문을 유지할 수 있습니까?
Thomas Eyde 2017 년

@ThomasEyde는 그들이 지난 15 년 동안해온 일입니다. 이것이 표현식 본문 멤버가 추가 된 방법이며 이제 튜플을 평가합니다. 레코드 스타일 클래스는이 버전의 C # 7에 대한 8 월 (이 주석 이전 9 개월)의 축소를 간신히 놓쳤으며 아마도 C # 8에서 나올 것입니다. 또한 튜플은 평범한 클래스가 제공하지 않는 값 동등성을 제공합니다 . 2002 년에이 모든 것을 도입하려면
예지력

당신은 무엇을 뜻합니까 convenient not to make a custom class. 을 사용하여 사용자 정의 클래스 인스턴스를 만드는 것을 의미 =new..()합니까?
Alex

75

튜플을 사용하면 2 차원 사전 (또는 해당 문제에 대한 n 차원)을 쉽게 구현할 수 있습니다. 예를 들어, 이러한 사전을 사용하여 통화 교환 매핑을 구현할 수 있습니다.

var forex = new Dictionary<Tuple<string, string>, decimal>();
forex.Add(Tuple.Create("USD", "EUR"), 0.74850m); // 1 USD = 0.74850 EUR
forex.Add(Tuple.Create("USD", "GBP"), 0.64128m);
forex.Add(Tuple.Create("EUR", "USD"), 1.33635m);
forex.Add(Tuple.Create("EUR", "GBP"), 0.85677m);
forex.Add(Tuple.Create("GBP", "USD"), 1.55938m);
forex.Add(Tuple.Create("GBP", "EUR"), 1.16717m);
forex.Add(Tuple.Create("USD", "USD"), 1.00000m);
forex.Add(Tuple.Create("EUR", "EUR"), 1.00000m);
forex.Add(Tuple.Create("GBP", "GBP"), 1.00000m);

decimal result;
result = 35.0m * forex[Tuple.Create("USD", "EUR")]; // USD 35.00 = EUR 26.20
result = 35.0m * forex[Tuple.Create("EUR", "GBP")]; // EUR 35.00 = GBP 29.99
result = 35.0m * forex[Tuple.Create("GBP", "USD")]; // GBP 35.00 = USD 54.58

국가 약어로 Enum을 사용하고 싶습니다. 가능합니까?
Zack

1
물론 열거 형은 값 유형이므로 문제없이 작동합니다.
MarioVW

@MarioVW 다차원 배열을 사용하여 수행 할 수도 있습니다. 튜플은 어떤 차이를 만들까요?
Alex

26

있다 우수한 기사는MSDN 매거진에는 BCL에 Tuple을 추가하는 데 따른 배타적 및 디자인 고려 사항에 대해 가 있습니다. 값 유형과 참조 유형 중에서 선택하는 것이 특히 흥미 롭습니다.

기사에서 분명하게 알 수 있듯이 Tuple의 원동력은 Microsoft 내부의 많은 그룹이 F # 팀을 사용하고 있다는 것입니다. 언급되지는 않았지만 C # (및 VB.NET)의 새로운 "dynamic"키워드도 이와 관련이 있다고 생각합니다. 튜플은 동적 언어에서 매우 일반적입니다.

그렇지 않으면 자신의 poco를 만드는 것보다 특히 우월하지 않습니다. 적어도 구성원에게 더 나은 이름을 줄 수 있습니다.


업데이트 : C # 버전 7의 큰 개정으로 인해 이제 훨씬 더 많은 구문 사랑을 받고 있습니다. 의 예비 발표이 블로그 게시물의 .


23

다음은 작은 예입니다. 사용자 ID가 주어지면 사용자의 핸들과 이메일 주소를 조회해야하는 메소드가 있다고 가정 해 보겠습니다. 항상 해당 데이터를 포함하는 사용자 지정 클래스를 만들거나 해당 데이터에 대한 ref / out 매개 변수를 사용하거나 새 POCO를 만들지 않고도 Tuple을 반환하고 멋진 메서드 서명을 가질 수 있습니다.

public static void Main(string[] args)
{
    int userId = 0;
    Tuple<string, string> userData = GetUserData(userId);
}

public static Tuple<string, string> GetUserData(int userId)
{
    return new Tuple<string, string>("Hello", "World");
}

10
그러나 이것은 좋은 예이지만 Tuple의 사용을 정당화하지 않습니다.
Amitabh

7
튜플은 고유 한 값을 반환하기 때문에 여기에 적합합니다. 그러나 튜플은 다른 유형의 여러 값을 반환 할 때 더 빛납니다 .
Mark Rushakoff 2010

21
또 다른 좋은 예는 int.TryParse입니다. 출력 매개 변수를 제거하고 대신 Tuple을 사용할 수 있습니다. 따라서 Tuple<bool, T> TryParse<T>(string input)출력 매개 변수를 사용하는 대신 두 값을 튜플에 다시 가져올 수 있습니다.
Tejs

3
실제로 F #에서 TryParse 메서드를 호출 할 때 발생하는 현상입니다.
Joel Mueller

23

Project Euler의 문제 11 을 해결하기 위해 튜플을 사용했습니다 .

class Grid
{
    public static int[,] Cells = { { 08, 02, 22, // whole grid omitted

    public static IEnumerable<Tuple<int, int, int, int>> ToList()
    {
        // code converts grid to enumeration every possible set of 4 per rules
        // code omitted
    }
}

이제 다음으로 전체 문제를 해결할 수 있습니다.

class Program
{
    static void Main(string[] args)
    {
        int product = Grid.ToList().Max(t => t.Item1 * t.Item2 * t.Item3 * t.Item4);
        Console.WriteLine("Maximum product is {0}", product);
    }
}

내가 할 수 이것에 대한 사용자 지정 형식을 사용하고 있지만 보았다 것입니다 정확히 튜플처럼 .


16

C #의 튜플 구문은 엄청나게 부피가 커서 튜플을 선언하기가 어렵습니다. 그리고 패턴 매칭이 없기 때문에 사용하기도 힘들다.

그러나 때로는 클래스를 생성하지 않고 객체의 임시 그룹화를 원합니다. 예를 들어 목록을 집계하고 싶지만 하나가 아닌 두 개의 값을 원한다고 가정 해 보겠습니다.

// sum and sum of squares at the same time
var x =
    Enumerable.Range(1, 100)
    .Aggregate((acc, x) => Tuple.Create(acc.Item1 + x, acc.Item2 + x * x));

값 모음을 단일 결과로 결합하는 대신 단일 결과를 값 모음으로 확장 해 보겠습니다. 이 함수를 작성하는 가장 쉬운 방법은 다음과 같습니다.

static IEnumerable<T> Unfold<T, State>(State seed, Func<State, Tuple<T, State>> f)
{
    Tuple<T, State> res;
    while ((res = f(seed)) != null)
    {
        yield return res.Item1;
        seed = res.Item2;
    }
}

f일부 상태를 튜플로 변환합니다. 튜플에서 첫 번째 값을 반환하고 새 상태를 두 번째 값으로 설정합니다. 이를 통해 계산 내내 상태를 유지할 수 있습니다.

다음과 같이 사용합니다.

// return 0, 2, 3, 6, 8
var evens =
    Unfold(0, state => state < 10 ? Tuple.Create(state, state + 2) : null)
    .ToList();

// returns 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
var fibs =
    Unfold(Tuple.Create(0, 1), state => Tuple.Create(state.Item1, Tuple.Create(state.Item2, state.Item1 + state.Item2)))
    .Take(10).ToList();

evens상당히 간단하지만 fibs조금 더 영리합니다. 그는 state실제 (N-1) 각각의 FIB (N-2)와 FIB를 유지하는 튜플이다.


4
1 Tuple.Create이 편리 속기입니다new Tuple<Guid,string,...>
AaronLS

국가의 사용은 키워드 @Juliet 무엇
irfandar

7

나는 그들 자신을 설명하지 않는 코드를 생성하기 때문에 그것들의 남용을 좋아하지 않지만 그들은 IStructuralEquatable 및 IStructuralComparable을 구현하기 때문에 즉석 복합 키를 구현하는 것이 굉장합니다 (조회 및 ​​주문에 모두 사용 목적).

그리고 그들은 내부적으로 모든 항목의 해시 코드를 결합합니다. 예를 들어 다음은 Tuple의 GetHashCode (ILSpy에서 가져옴)입니다.

    int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
    {
        return Tuple.CombineHashCodes(comparer.GetHashCode(this.m_Item1), comparer.GetHashCode(this.m_Item2), comparer.GetHashCode(this.m_Item3));
    }

7

튜플은 한 번에 여러 비동기 IO 작업을 수행하고 모든 값을 함께 반환하는 데 적합합니다. 다음은 Tuple을 사용하거나 사용하지 않고 수행하는 예입니다. 튜플은 실제로 코드를 더 명확하게 만들 수 있습니다!

없이 (불쾌한 중첩!) :

Task.Factory.StartNew(() => data.RetrieveServerNames())
    .ContinueWith(antecedent1 =>
        {
            if (!antecedent1.IsFaulted)
            {
                ServerNames = KeepExistingFilter(ServerNames, antecedent1.Result);
                Task.Factory.StartNew(() => data.RetrieveLogNames())
                    .ContinueWith(antecedent2 =>
                        {
                            if (antecedent2.IsFaulted)
                            {
                                LogNames = KeepExistingFilter(LogNames, antecedent2.Result);
                                Task.Factory.StartNew(() => data.RetrieveEntryTypes())
                                    .ContinueWith(antecedent3 =>
                                        {
                                            if (!antecedent3.IsFaulted)
                                            {
                                                EntryTypes = KeepExistingFilter(EntryTypes, antecedent3.Result);
                                            }
                                        });
                            }
                        });
            }
        });

튜플 사용

Task.Factory.StartNew(() =>
    {
        List<string> serverNames = data.RetrieveServerNames();
        List<string> logNames = data.RetrieveLogNames();
        List<string> entryTypes = data.RetrieveEntryTypes();
        return Tuple.Create(serverNames, logNames, entryTypes);
    }).ContinueWith(antecedent =>
        {
            if (!antecedent.IsFaulted)
            {
                ServerNames = KeepExistingFilter(ServerNames, antecedent.Result.Item1);
                LogNames = KeepExistingFilter(LogNames, antecedent.Result.Item2);
                EntryTypes = KeepExistingFilter(EntryTypes, antecedent.Result.Item3);
            }
        });

어쨌든 묵시적 유형으로 익명 함수를 사용했다면 Tuple을 사용하여 코드를 덜 명확하게 만들지 않습니다. 메서드에서 튜플을 다시 조정합니까? 내 겸손한 의견으로는 코드 명확성이 핵심 일 때는 아껴 사용하십시오. 나는 C #의 함수형 프로그래밍이 저항하기 어렵다는 것을 알고 있지만, 우리는 그 옛날 투박한 "객체 지향"C # 프로그래머들을 모두 고려해야합니다.


5

튜플은 더 많은 작업을 수행 할 수있는 기능적 언어에서 많이 사용됩니다. 이제 F #은 C #에서 상호 운용하고 두 언어로 작성된 코드간에 전달할 수있는 '공식'.net 언어입니다.


또한 튜플은 Python 및 Ruby와 같은 일부 인기있는 스크립팅 언어에 대한 유형으로 빌드됩니다.
MutantNinjaCodeMonkey

5

나는 Tuple가독성을 떨어 뜨리기 때문에 대부분의 시나리오 를 피하는 경향이 있습니다. 하나,Tuple 관련없는 데이터를 그룹화해야하는 경우 유용합니다.

예를 들어 자동차 목록과 해당 자동차를 구입 한 도시가 있다고 가정합니다.

Mercedes, Seattle
Mustang, Denver
Mercedes, Seattle
Porsche, Seattle
Tesla, Seattle
Mercedes, Seattle

도시 당 각 자동차의 수를 집계하려고합니다.

Mercedes, Seattle [3]
Mustang, Denver [1]
Porsche, Seattle [1]
Tesla, Seattle [1]

이렇게하려면 Dictionary. 몇 가지 옵션이 있습니다.

  1. 을 만듭니다 Dictionary<string, Dictionary<string, int>>.
  2. 을 만듭니다 Dictionary<CarAndCity, int>.
  3. 을 만듭니다 Dictionary<Tuple<string, string>, int>.

첫 번째 옵션을 사용하면 가독성이 손실됩니다. 더 많은 코드를 작성해야합니다.

두 번째 옵션은 작동하고 간결하지만 자동차와 도시는 실제로 관련이 없으며 아마도 함께 수업에 속하지 않을 것입니다.

세 번째 옵션은 간결하고 깔끔합니다. 의 좋은 사용입니다 Tuple.


4

내 머릿속에서 몇 가지 예 :

  • X 및 Y 위치 (원하는 경우 Z 포함)
  • 너비와 높이
  • 시간이 지남에 따라 측정되는 모든 것

예를 들어 Point / PointF 및 Size / SizeF를 사용하기 위해 웹 응용 프로그램에 System.Drawing을 포함하고 싶지는 않을 것입니다.


2
Tuple중요한 상황에서 유용 Point하거나 SomeVector그래픽 작업을 할 때 유용 할 수 있습니다. 서로 밀접하게 연결된 두 가지 가치를 강조합니다. 코드를 읽을 때 종종 StartTime 및 EndTime이라는 속성이 표시되지만 날짜 시간 및 기간보다 더 나은 Tuple은 비즈니스 논리의이 영역에서 작업 할 때마다 두 값을 모두 고려해야합니다. 또는 "hey, data has changed (bool), here is the data (other type)"를 반환하는 대신 집중적 인 바인딩을 거치지 않습니다.
Léon Pelletier

3

당신은 사용에 매우주의해야 Tuple하고 아마 이것을하기 전에 두 번 생각해야합니다. 이전 경험을 통해 나는 Tuple코드 를 사용 하면 앞으로 코드를 읽고 지원하기가 매우 어렵다는 것을 알았습니다 . 얼마 전 거의 모든 곳에서 튜플이 사용되는 코드를 수정해야했습니다. 적절한 객체 모델을 생각하는 대신 튜플을 사용했습니다. 악몽 이었어요 ... 때로는 코드를 작성한 사람을 죽이고 싶었어요 ...

당신이 사용해서는 안된다고 말하고 싶지 않고 Tuple, 그것은 악한 것 같은 것입니다. 그리고 저는 그것이 사용 Tuple하기에 가장 좋은 후보 가되는 몇 가지 작업이 있다고 확신합니다. 그러나 아마 당신은 다시 생각해야합니다. ?


1

내가 찾은 튜플의 가장 좋은 용도는 메서드에서 둘 이상의 객체 유형을 반환해야 할 때 어떤 객체 유형과 번호가 될지 알고 있으며 긴 목록이 아닙니다.

다른 간단한 대안은 'out'매개 변수를 사용하는 것입니다.

private string MyMethod(out object)

또는 사전 만들기

Dictionary<objectType1, objectType2>

그러나 튜플을 사용하면 'out'객체를 만들거나 기본적으로 사전에서 항목을 조회 할 필요가 없습니다.


1

Tuple에서 내 문제 중 하나의 해결책을 찾았습니다. 메서드의 범위에서 클래스를 선언하는 것과 비슷하지만 필드 이름의 지연 선언이 있습니다. 튜플 컬렉션, 단일 인스턴스로 작업 한 다음 튜플을 기반으로 필수 필드 이름을 사용하여 익명 유형 컬렉션을 만듭니다. 이렇게하면 이러한 목적으로 새 클래스를 만들 수 없습니다.

작업은 추가 클래스없이 LINQ에서 JSON 응답을 작성하는 것입니다.

 //I select some roles from my ORM my with subrequest and save results to Tuple list
 var rolesWithUsers = (from role in roles
                       select new Tuple<string, int, int>(
                         role.RoleName, 
                         role.RoleId, 
                         usersInRoles.Where(ur => ur.RoleId == role.RoleId).Count()
                      ));

 //Then I add some new element required element to this collection
 var tempResult = rolesWithUsers.ToList();
 tempResult.Add(new Tuple<string, int, int>(
                        "Empty", 
                         -1,
                         emptyRoleUsers.Count()
                      ));

 //And create a new anonimous class collection, based on my Tuple list
 tempResult.Select(item => new
            {
                GroupName = item.Item1,
                GroupId = item.Item2,
                Count = item.Item3
            });


 //And return it in JSON
 return new JavaScriptSerializer().Serialize(rolesWithUsers);

왜냐면 우리는 우리 그룹을위한 새로운 클래스를 선언함으로써 이것을 할 수 있지만, 새로운 클래스를 선언하지 않고 그러한 익명의 컬렉션을 만드는 아이디어입니다.


1

제 경우에는 비동기 메서드에서 out 매개 변수를 사용할 수 없다는 것을 알았을 때 Tuple을 사용해야했습니다. 여기에서 그것에 대해 읽어보십시오 . 또한 다른 반환 유형이 필요했습니다. 그래서 대신 Tuple을 반환 유형으로 사용하고 메서드를 비동기로 표시했습니다.

아래 샘플 코드.

...
...
// calling code.
var userDetails = await GetUserDetails(userId);
Console.WriteLine("Username : {0}", userDetails.Item1);
Console.WriteLine("User Region Id : {0}", userDetails.Item2);
...
...

private async Tuple<string,int> GetUserDetails(int userId)
{
    return new Tuple<string,int>("Amogh",105);
    // Note that I can also use the existing helper method (Tuple.Create).
}

여기에서 튜플 에 대해 자세히 알아보십시오 . 도움이 되었기를 바랍니다.


난 당신이 익명의 유형 또는 배열 (또는 동적 내용)을 반환하고 싶지 않은 가정
ozzy432836

0

와이어를 통해 보내거나 다른 응용 프로그램 레이어로 전달해야 할 때 개체의 모양을 변경하면 여러 개체가 하나로 병합됩니다.

예:

var customerDetails = new Tuple<Customer, List<Address>>(mainCustomer, new List<Address> {mainCustomerAddress}).ToCustomerDetails();

ExtensionMethod :

public static CustomerDetails ToCustomerDetails(this Tuple<Website.Customer, List<Website.Address>> customerAndAddress)
    {
        var mainAddress = customerAndAddress.Item2 != null ? customerAndAddress.Item2.SingleOrDefault(o => o.Type == "Main") : null;
        var customerDetails = new CustomerDetails
        {
            FirstName = customerAndAddress.Item1.Name,
            LastName = customerAndAddress.Item1.Surname,
            Title = customerAndAddress.Item1.Title,
            Dob = customerAndAddress.Item1.Dob,
            EmailAddress = customerAndAddress.Item1.Email,
            Gender = customerAndAddress.Item1.Gender,
            PrimaryPhoneNo = string.Format("{0}", customerAndAddress.Item1.Phone)
        };

        if (mainAddress != null)
        {
            customerDetails.AddressLine1 =
                !string.IsNullOrWhiteSpace(mainAddress.HouseName)
                    ? mainAddress.HouseName
                    : mainAddress.HouseNumber;
            customerDetails.AddressLine2 =
                !string.IsNullOrWhiteSpace(mainAddress.Street)
                    ? mainAddress.Street
                    : null;
            customerDetails.AddressLine3 =
                !string.IsNullOrWhiteSpace(mainAddress.Town) ? mainAddress.Town : null;
            customerDetails.AddressLine4 =
                !string.IsNullOrWhiteSpace(mainAddress.County)
                    ? mainAddress.County
                    : null;
            customerDetails.PostCode = mainAddress.PostCode;
        }
...
        return customerDetails;
    }

0

out 매개 변수는 반환해야하는 값이 적을 때 유용하지만 반환해야하는 값이 4, 5, 6 또는 그 이상일 때 다루기 어려울 수 있습니다. 여러 값을 반환하는 또 다른 옵션은 사용자 정의 클래스 / 구조를 만들고 반환하거나 튜플을 사용하여 메서드에서 반환해야하는 모든 값을 패키지화하는 것입니다.

클래스 / 구조를 사용하여 값을 반환하는 첫 번째 옵션은 간단합니다. 다음과 같이 유형 (이 예에서는 구조)을 작성하십시오.

public struct Dimensions
{
public int Height;
public int Width;
public int Depth;
}

튜플을 사용하는 두 번째 옵션은 사용자 정의 개체를 사용하는 것보다 훨씬 더 우아한 솔루션입니다. 다양한 유형의 값을 원하는만큼 보유하도록 튜플을 만들 수 있습니다. 또한 Tuple에 저장하는 데이터는 변경할 수 없습니다. 생성자 또는 정적 Create 메서드를 통해 Tuple에 데이터를 추가하면 해당 데이터를 변경할 수 없습니다. 튜플은 최대 8 개의 개별 값을 허용 할 수 있습니다. 8 개 이상의 값을 반환해야하는 경우 특수 Tuple 클래스를 사용해야합니다. Tuple 클래스 8 개 이상의 값이있는 Tuple을 만들 때는 정적 Create 메서드를 사용할 수 없습니다. 대신 클래스의 생성자를 사용해야합니다. 다음은 10 개의 정수 값으로 구성된 튜플을 만드는 방법입니다.

var values = new Tuple<int, int, int, int, int, int, int, Tuple<int, int, int>> (
1, 2, 3, 4, 5, 6, 7, new Tuple<int, int, int> (8, 9, 10));

물론 각 임베디드 튜플 끝에 더 많은 튜플을 계속 추가하여 필요한 크기의 튜플을 만들 수 있습니다.


0

프로토 타이핑 전용-튜플은 의미가 없습니다. 사용하기 편리하지만 바로 가기 일뿐입니다! 프로토 타입의 경우-좋습니다. 나중에이 코드를 삭제하십시오.

쓰기 쉽고 읽기 어렵습니다. 클래스, 내부 클래스, 익명 클래스 등에 비해 눈에 띄는 이점이 없습니다.


0

C # 7에서 동일한 문제를 해결하기 위해 3 가지 방법을 시도했고 Tuples에 대한 사용 사례를 찾았습니다.

웹 프로젝트에서 동적 데이터로 작업하는 것은 매핑 등에서 때때로 고통 스러울 수 있습니다.

나는 튜플이 item1, item2, itemN에 자동으로 매핑되는 방식을 좋아하는데, 이는 인덱스 항목에서 잡힐 수있는 배열 인덱스를 사용하거나 속성 이름을 잘못 입력 할 수있는 익명 유형을 사용하는 것보다 더 강력 해 보입니다.

Tuple을 사용하는 것만으로 DTO가 무료로 생성 된 것 같고, 별도의 DTO를 만들지 않고도 정적 타이핑처럼 느껴지는 itemN을 사용하여 모든 속성에 액세스 할 수 있습니다.

using System;

namespace Playground
{
    class Program
    {
        static void Main(string[] args)
        {
            var tuple = GetTuple();
            Console.WriteLine(tuple.Item1);
            Console.WriteLine(tuple.Item2);
            Console.WriteLine(tuple.Item3);
            Console.WriteLine(tuple);

            Console.WriteLine("---");

            var dyn = GetDynamic();
            Console.WriteLine(dyn.First);
            Console.WriteLine(dyn.Last);
            Console.WriteLine(dyn.Age);
            Console.WriteLine(dyn);

            Console.WriteLine("---");

            var arr = GetArray();
            Console.WriteLine(arr[0]);
            Console.WriteLine(arr[1]);
            Console.WriteLine(arr[2]);
            Console.WriteLine(arr);

            Console.Read();

            (string, string, int) GetTuple()
            {
                return ("John", "Connor", 1);
            }

            dynamic GetDynamic()
            {
                return new { First = "John", Last = "Connor", Age = 1 };
            }

            dynamic[] GetArray()
            {
                return new dynamic[] { "John", "Connor", 1 };
            }
        }
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.