다음을 통해 공유


데이터 계약의 컬렉션 형식

컬렉션은 특정 형식의 항목 목록입니다. .NET Framework에서 이러한 목록은 배열 또는 다양한 다른 형식(제네릭 목록, 제네릭 BindingList<T>StringCollection또는ArrayList)을 사용하여 나타낼 수 있습니다. 예를 들어 컬렉션에는 지정된 고객에 대한 주소 목록이 포함될 수 있습니다. 이러한 컬렉션은 실제 형식 에 관계없이 목록 컬렉션이라고 합니다.

한 항목("키")과 다른 항목("값") 간의 연결을 나타내는 특수한 형식의 컬렉션이 있습니다. .NET Framework에서 이러한 항목은 제네릭 사전과 같은 형식으로 Hashtable 표시됩니다. 예를 들어, 연관 컬렉션은 도시("키")를 인구("값")에 매핑할 수 있습니다. 이러한 컬렉션은 실제 형식 에 관계없이 사전 컬렉션이라고 합니다.

컬렉션은 데이터 계약 모델에서 특별한 처리를 받습니다.

배열 및 제네릭 컬렉션을 포함하여 인터페이스를 구현 IEnumerable 하는 형식은 컬렉션으로 인식됩니다. 이 중 IDictionary 또는 제네릭 IDictionary<TKey,TValue> 인터페이스를 구현하는 형식은 사전 컬렉션이고, 다른 모든 형식은 목록 컬렉션입니다.

다음 섹션에서는 메서드 호출 Add 및 매개 변수 없는 생성자와 같은 컬렉션 형식에 대한 추가 요구 사항을 자세히 설명합니다. 이렇게 하면 컬렉션 형식을 직렬화 및 역직렬화할 수 있습니다. 즉, 제네릭 ReadOnlyCollection<T> 과 같은 일부 컬렉션은 직접 지원되지 않습니다(매개 변수가 없는 생성자가 없기 때문). 그러나 이러한 제한을 우회하는 방법에 대한 자세한 내용은 이 항목의 뒷부분에 있는 "컬렉션 인터페이스 형식 및 Read-Only 컬렉션 사용" 섹션을 참조하세요.

컬렉션에 포함된 형식은 데이터 계약 형식이거나 직렬화할 수 있어야 합니다. 자세한 내용은 데이터 계약 직렬 변환기에서 지원하는 형식을 참조하세요.

유효한 컬렉션으로 간주되지 않는 항목과 컬렉션이 serialize되는 방법에 대한 자세한 내용은 이 항목의 "고급 컬렉션 규칙" 섹션에서 컬렉션 직렬화에 대한 정보를 참조하세요.

교환 가능한 컬렉션

동일한 형식의 모든 목록 컬렉션은 동일한 데이터 계약을 갖는 것으로 간주됩니다(이 항목의 CollectionDataContractAttribute 뒷부분에서 설명한 대로 특성을 사용하여 사용자 지정되지 않는 한). 따라서 예를 들어 다음 데이터 계약은 동일합니다.

[DataContract(Name = "PurchaseOrder")]
public class PurchaseOrder1
{
    [DataMember]
    public string customerName;
    [DataMember]
    public Collection<Item> items;
    [DataMember]
    public string[] comments;
}

[DataContract(Name = "PurchaseOrder")]
public class PurchaseOrder2
{
    [DataMember]
    public string customerName;
    [DataMember]
    public List<Item> items;
    [DataMember]
    public BindingList<string> comments;
}
<DataContract(Name:="PurchaseOrder")>
Public Class PurchaseOrder1

    <DataMember()>
    Public customerName As String

    <DataMember()>
    Public items As Collection(Of Item)

    <DataMember()>
    Public comments() As String

End Class

<DataContract(Name:="PurchaseOrder")>
Public Class PurchaseOrder2

    <DataMember()>
    Public customerName As String

    <DataMember()>
    Public items As List(Of Item)

    <DataMember()>
    Public comments As BindingList(Of String)

End Class

두 데이터 계약 모두 다음 코드와 유사한 XML을 생성합니다.

<PurchaseOrder>
    <customerName>...</customerName>
    <items>
        <Item>...</Item>
        <Item>...</Item>
        <Item>...</Item>
        ...
    </items>
    <comments>
        <string>...</string>
        <string>...</string>
        <string>...</string>
        ...
    </comments>
</PurchaseOrder>

컬렉션 교환성을 사용하면 서버의 성능에 최적화된 컬렉션 형식과 클라이언트의 사용자 인터페이스 구성 요소에 바인딩되도록 설계된 컬렉션 형식을 사용할 수 있습니다.

목록 컬렉션과 마찬가지로 키 및 값 형식이 동일한 모든 사전 컬렉션은 동일한 데이터 계약을 갖는 것으로 간주됩니다(특성에 의해 CollectionDataContractAttribute 사용자 지정되지 않은 경우).

.NET 형식이 아니라 컬렉션 동등성에 관한 한 데이터 계약 형식만 중요합니다. 즉, Type1 및 Type2에 동일한 데이터 계약이 있는 경우 Type1의 컬렉션은 Type2 컬렉션과 동일한 것으로 간주됩니다.

제네릭이 아닌 컬렉션은 형식 Object의 제네릭 컬렉션과 동일한 데이터 계약을 갖는 것으로 간주됩니다. (예를 들어, ArrayList와 제네릭 List<T>Object 데이터 계약은 동일합니다.)

컬렉션 인터페이스 형식 및 Read-Only 컬렉션 사용

컬렉션 인터페이스 형식(IEnumerableIDictionary이러한 인터페이스에서 파생된 제네릭 IDictionary<TKey,TValue>또는 인터페이스)도 실제 컬렉션 형식에 대한 컬렉션 데이터 계약과 동일한 컬렉션 데이터 계약을 갖는 것으로 간주됩니다. 따라서 컬렉션 인터페이스 형식으로 serialize되는 형식을 선언할 수 있으며 결과는 실제 컬렉션 형식이 사용된 경우와 동일합니다. 예를 들어 다음 데이터 계약은 동일합니다.

[DataContract(Name="Customer")]
public class Customer1
{
    [DataMember]
    public string customerName;
    [DataMember]
    public Collection<Address> addresses;
}

[DataContract(Name="Customer")]
public class Customer2
{
    [DataMember]
    public string customerName;
    [DataMember]
    public ICollection<Address> addresses;
}
<DataContract(Name:="Customer")>
Public Class Customer1

    <DataMember()>
    Public customerName As String

    <DataMember()>
    Public addresses As Collection(Of Address)

End Class

<DataContract(Name:="Customer")>
Public Class Customer2

    <DataMember()>
    Public customerName As String

    <DataMember()>
    Public addresses As ICollection(Of Address)

End Class

serialization 중에 선언된 형식이 인터페이스인 경우 사용되는 실제 인스턴스 형식은 해당 인터페이스를 구현하는 모든 형식일 수 있습니다. 앞에서 설명한 제한 사항(매개 변수가 없는 생성자 및 Add 메서드 포함)은 적용되지 않습니다. 예를 들어, 주소의 제네릭 ReadOnlyCollection<T> 인스턴스로 Customer2의 주소를 설정할 수 있지만, 제네릭 ReadOnlyCollection<T> 형식의 데이터 멤버를 직접 선언할 수는 없습니다.

역직렬화 중에 선언된 형식이 인터페이스인 경우 serialization 엔진은 선언된 인터페이스를 구현하는 형식을 선택하고 형식을 인스턴스화합니다. 알려진 형식 메커니즘( 데이터 계약 알려진 형식에 설명됨)은 여기에 영향을 주지 않습니다. 형식 선택은 WCF에 기본 제공됩니다.

컬렉션 형식 사용자 지정

여러 가지 용도가 있는 특성을 사용하여 컬렉션 형식을 CollectionDataContractAttribute 사용자 지정할 수 있습니다.

컬렉션 형식을 사용자 지정하면 컬렉션의 상호 교환성이 손상되므로 가능하면 이 특성을 적용하지 않는 것이 좋습니다. 이 문제에 대한 자세한 내용은 이 항목의 뒷부분에 있는 "고급 컬렉션 규칙" 섹션을 참조하세요.

컬렉션 데이터 계약 명명

몇 가지 중요한 차이점이 있지만 데이터 계약 이름에 설명된 대로 컬렉션 형식의 명명 규칙은 일반 데이터 계약 형식의 이름을 지정하는 규칙과 유사합니다.

  • CollectionDataContractAttribute 속성은 DataContractAttribute 속성 대신 이름을 사용자 지정하는 데 사용됩니다. CollectionDataContractAttribute 속성에는 NameNamespace 속성도 있습니다.

  • 특성이 CollectionDataContractAttribute 적용되지 않으면 컬렉션 형식의 기본 이름 및 네임스페이스는 컬렉션에 포함된 형식의 이름과 네임스페이스에 따라 달라집니다. 컬렉션 형식 자체의 이름 및 네임스페이스의 영향을 받지 않습니다. 예제는 다음 형식을 참조하세요.

    public CustomerList1 : Collection<string> {}
    public StringList1 : Collection<string> {}
    

두 형식의 데이터 계약 이름은 "CustomerList1" 또는 "StringList1"이 아닌 "ArrayOfstring"입니다. 즉, 루트 수준에서 이러한 형식 중 하나를 직렬화하면 다음 코드와 유사한 XML이 생성됩니다.

<ArrayOfstring>
    <string>...</string>
    <string>...</string>
    <string>...</string>
    ...
</ArrayOfstring>

이 명명 규칙은 문자열 목록을 나타내는 사용자 지정되지 않은 형식이 동일한 데이터 계약 및 XML 표현을 갖도록 하기 위해 선택되었습니다. 이렇게 하면 컬렉션의 상호 교환이 가능합니다. 이 예제에서는 CustomerList1 및 StringList1을 완전히 교환할 수 있습니다.

그러나 특성이 CollectionDataContractAttribute 적용되면 특성에 설정된 속성이 없더라도 컬렉션은 사용자 지정된 컬렉션 데이터 계약이 됩니다. 그런 다음 컬렉션 데이터 계약의 이름 및 네임스페이스는 컬렉션 형식 자체에 따라 달라집니다. 예제는 다음 형식을 참조하세요.

[CollectionDataContract]
public class CustomerList2 : Collection<string> {}
<CollectionDataContract()>
Public Class CustomerList2
    Inherits Collection(Of String)
End Class

serialize할 때 결과 XML은 다음과 유사합니다.

<CustomerList2>
    <string>...</string>
    <string>...</string>
    <string>...</string>
    ...
</CustomerList2>

이는 더 이상 사용자 지정되지 않은 형식의 XML 표현과 동일하지 않습니다.

  • NameNamespace 속성을 사용하여 이름을 더 사용자 지정할 수 있습니다. 다음 클래스를 참조하세요.

    [CollectionDataContract(Name="cust_list")]
    public class CustomerList3 : Collection<string> {}
    
    <CollectionDataContract(Name:="cust_list")>
    Public Class CustomerList3
        Inherits Collection(Of String)
    End Class
    

결과 XML은 다음과 유사합니다.

<cust_list>
    <string>...</string>
    <string>...</string>
    <string>...</string>
    ...
</cust_list>

자세한 내용은 이 항목의 뒷부분에 있는 "고급 컬렉션 규칙" 섹션을 참조하세요.

목록 컬렉션에서 반복 요소 이름 사용자 지정

목록 컬렉션에는 반복 항목이 포함됩니다. 일반적으로 각 반복 항목은 컬렉션에 포함된 형식의 데이터 계약 이름에 따라 명명된 요소로 표시됩니다.

예제에서 CustomerList 컬렉션에는 문자열이 포함되어 있습니다. 문자열 기본 형식의 데이터 계약 이름은 "string"이므로 반복 요소는 "<string>"입니다.

그러나 특성에서 ItemName 속성을 CollectionDataContractAttribute에 사용하여 이 반복되는 요소의 이름을 사용자 지정할 수 있습니다. 예제는 다음 형식을 참조하세요.

[CollectionDataContract(ItemName="customer")]
public class CustomerList4 : Collection<string>  {}
<CollectionDataContract(ItemName:="customer")>
Public Class CustomerList4
    Inherits Collection(Of String)
End Class

결과 XML은 다음과 유사합니다.

<CustomerList4>
    <customer>...</customer>
    <customer>...</customer>
    <customer>...</customer>
    ...
</CustomerList4>

반복 요소의 네임스페이스는 항상 컬렉션 데이터 계약의 네임스페이스와 동일하며, 앞에서 설명한 대로 속성을 사용하여 Namespace 사용자 지정할 수 있습니다.

사전 컬렉션 사용자 지정

사전 컬렉션은 기본적으로 각 항목에 키와 값이 있는 항목의 목록입니다. 일반 목록과 마찬가지로 속성을 사용하여 ItemName 반복 요소에 해당하는 요소 이름을 변경할 수 있습니다.

또한 키 및 속성을 사용하여 KeyNameValueName 키와 값을 나타내는 요소 이름을 변경할 수 있습니다. 이러한 요소의 네임스페이스는 컬렉션 데이터 계약의 네임스페이스와 동일합니다.

예제는 다음 형식을 참조하세요.

[CollectionDataContract
    (Name = "CountriesOrRegionsWithCapitals",
    ItemName = "entry",
    KeyName = "countryorregion",
    ValueName = "capital")]
public class CountriesOrRegionsWithCapitals2 : Dictionary<string, string> { }
<CollectionDataContract(Name:="CountriesOrRegionsWithCapitals",
                        ItemName:="entry", KeyName:="countryorregion",
                        ValueName:="capital")>
Public Class CountriesOrRegionsWithCapitals2
    Inherits Dictionary(Of String, String)
End Class

serialize할 때 결과 XML은 다음과 유사합니다.

<CountriesOrRegionsWithCapitals>
    <entry>
        <countryorregion>USA</countryorregion>
        <capital>Washington</capital>
    </entry>
    <entry>
        <countryorregion>France</countryorregion>
        <capital>Paris</capital>
    </entry>
    ...
</CountriesOrRegionsWithCapitals>

사전 컬렉션에 대한 자세한 내용은 이 항목의 뒷부분에 있는 "고급 컬렉션 규칙" 섹션을 참조하세요.

컬렉션 및 알려진 형식

다른 컬렉션 또는 컬렉션 인터페이스 대신 다형적으로 사용되는 경우 알려진 형식에 컬렉션 형식을 추가할 필요가 없습니다. 예를 들어 형식 IEnumerable 의 데이터 멤버를 선언하고 이를 사용하여 인스턴스 ArrayList를 보내는 경우 알려진 형식에 추가할 ArrayList 필요가 없습니다.

컬렉션이 아닌 형식 대신 다형적으로 컬렉션을 사용하는 경우 알려진 형식에 컬렉션을 추가해야 합니다. 예를 들어 형식 Object 의 데이터 멤버를 선언하고 이를 사용하여 인스턴스를 ArrayList보내는 경우 알려진 형식에 추가 ArrayList 합니다.

이렇게 하면 해당하는 컬렉션을 다형적으로 직렬화할 수 없습니다. 예를 들어 앞의 예제에서 ArrayList을(를) 알려진 형식 목록에 추가해도, 동일한 데이터 계약이 있더라도 Array of Object 클래스를 할당할 수 없습니다. 이는 컬렉션이 아닌 형식의 serialization에 대해 알려진 일반 형식 동작과 다르지 않지만 컬렉션이 동일한 것이 매우 일반적이기 때문에 컬렉션의 경우를 이해하는 것이 특히 중요합니다.

serialization 중에는 지정된 데이터 계약에 대해 지정된 범위에서 하나의 형식만 알 수 있으며, 해당하는 컬렉션에는 모두 동일한 데이터 계약이 있습니다. 즉, 이전 예제에서는 동일한 범위에서 알려진 형식에 ArrayListArray of Object를 동시에 추가할 수 없습니다. 이 동작은 컬렉션이 아닌 형식의 알려진 형식 동작과 동일하지만 컬렉션에 대해 이해하는 것이 특히 중요합니다.

컬렉션의 내용에도 알려진 형식이 필요할 수 있습니다. 예를 들어 ArrayList에 실제로 Type1Type2의 인스턴스가 포함된 경우, 이 두 형식 모두를 알려진 형식에 추가해야 합니다.

다음 예제에서는 컬렉션 및 알려진 형식을 사용하여 올바르게 생성된 개체 그래프를 보여 줍니다. 실제 애플리케이션에서는 일반적으로 다음 데이터 멤버 Object를 정의하지 않으므로 알려진 형식/다형성 문제가 없으므로 이 예제는 다소 모순됩니다.

[DataContract]
public class Employee
{
    [DataMember]
    public string name = "John Doe";
    [DataMember]
    public Payroll payrollRecord;
    [DataMember]
    public Training trainingRecord;
}

[DataContract]
[KnownType(typeof(int[]))] //required because int[] is used polymorphically
[KnownType(typeof(ArrayList))] //required because ArrayList is used polymorphically
public class Payroll
{
    [DataMember]
    public object salaryPayments = new int[12];
    //float[] not needed in known types because polymorphic assignment is to another collection type
    [DataMember]
    public IEnumerable<float> stockAwards = new float[12];
    [DataMember]
    public object otherPayments = new ArrayList();
}

[DataContract]
[KnownType(typeof(List<object>))]
//required because List<object> is used polymorphically
//does not conflict with ArrayList above because it's a different scope,
//even though it's the same data contract
[KnownType(typeof(InHouseTraining))] //Required if InHouseTraining can be used in the collection
[KnownType(typeof(OutsideTraining))] //Required if OutsideTraining can be used in the collection
public class Training
{
    [DataMember]
    public object training = new List<object>();
}

[DataContract]
public class InHouseTraining
{
    //code omitted
}

[DataContract]
public class OutsideTraining
{
    //code omitted
}
<DataContract()>
Public Class Employee

    <DataMember()>
    Public name As String = "John Doe"

    <DataMember()>
    Public payrollRecord As Payroll

    <DataMember()>
    Public trainingRecord As Training

End Class

<DataContract(), KnownType(GetType(Integer())), KnownType(GetType(ArrayList))>
Public Class Payroll

    <DataMember()>
    Public salaryPayments As Object = New Integer(11) {}

    'float[] not needed in known types because polymorphic assignment is to another collection type
    <DataMember()>
    Public stockAwards As IEnumerable(Of Single) = New Single(11) {}

    <DataMember()>
    Public otherPayments As Object = New ArrayList()

End Class

'required because List<object> is used polymorphically
'does not conflict with ArrayList above because it's a different scope, 
'even though it's the same data contract
<DataContract(), KnownType(GetType(List(Of Object))),
                 KnownType(GetType(InHouseTraining)),
                 KnownType(GetType(OutsideTraining))>
Public Class Training
    <DataMember()>
    Public training As Object = New List(Of Object)()
End Class

<DataContract()>
Public Class InHouseTraining
    'code omitted…
End Class

<DataContract()>
Public Class OutsideTraining
    'code omitted…
End Class

역직렬화에서 선언된 형식이 컬렉션 형식인 경우 실제로 전송된 형식에 관계없이 선언된 형식이 인스턴스화됩니다. 선언된 형식이 컬렉션 인터페이스인 경우 역직렬 변환기는 알려진 형식과 관계없이 인스턴스화할 형식을 선택합니다.

또한 역직렬화 시 선언된 형식이 컬렉션 형식이 아니지만 컬렉션 형식이 전송되는 경우 알려진 형식 목록에서 일치하는 컬렉션 형식이 선택됩니다. 역직렬화에서 알려진 형식 목록에 컬렉션 인터페이스 형식을 추가할 수 있습니다. 이 경우 역직렬화 엔진은 인스턴스화할 형식을 다시 선택합니다.

컬렉션 및 NetDataContractSerializer 클래스

클래스를 NetDataContractSerializer 사용 중인 경우 배열이 아닌 사용자 지정되지 않은 컬렉션 형식(특성 제외 CollectionDataContractAttribute )은 특별한 의미를 잃게 됩니다.

사용자 지정되지 않은 컬렉션 형식은 SerializableAttribute 특성으로 표시되어 있을 경우, NetDataContractSerializer 클래스가 SerializableAttribute에 따라 또는 ISerializable 인터페이스 규칙에 따라 serialize할 수 있습니다.

사용자 지정된 컬렉션 형식, 컬렉션 인터페이스 및 배열은 클래스가 사용 중인 경우에도 NetDataContractSerializer 여전히 컬렉션으로 처리됩니다.

컬렉션 및 스키마

해당하는 모든 컬렉션은 XSD(XML 스키마 정의 언어) 스키마에서 동일한 표현을 가집니다. 따라서 일반적으로 생성된 클라이언트 코드에서 서버의 컬렉션 형식과 동일한 컬렉션 형식을 얻지 않습니다. 예를 들어 서버는 제네릭 정수 List<T> 데이터 멤버와 데이터 계약을 사용할 수 있지만 생성된 클라이언트 코드에서 동일한 데이터 멤버가 정수 배열이 될 수 있습니다.

사전 컬렉션은 사전임을 나타내는 WCF 관련 스키마 주석으로 표시됩니다. 그렇지 않으면 키와 값이 있는 항목을 포함하는 단순 목록과 구별할 수 없습니다. 데이터 계약 스키마에서 컬렉션을 나타내는 방법에 대한 정확한 설명은 데이터 계약 스키마 참조를 참조하세요.

기본적으로 형식은 가져온 코드에서 사용자 지정되지 않은 컬렉션에 대해 생성되지 않습니다. 목록 컬렉션 형식의 데이터 멤버를 배열로 가져오고 사전 컬렉션 형식의 데이터 멤버를 제네릭 사전으로 가져옵니다.

그러나 사용자 지정된 컬렉션의 경우 특성으로 표시된 별도의 형식이 CollectionDataContractAttribute 생성됩니다. 스키마의 사용자 지정된 컬렉션 형식은 기본 네임스페이스, 이름, 반복 요소 이름 또는 키/값 요소 이름을 사용하지 않는 컬렉션 형식입니다. 이러한 형식은 목록 형식의 경우 제네릭 List<T> 에서 파생되는 빈 형식이고 사전 형식의 경우 제네릭 사전입니다.

예를 들어 서버에 다음 형식이 있을 수 있습니다.

[DataContract]
public class CountryOrRegion
{
    [DataMember]
    public Collection<string> officialLanguages;
    [DataMember]
    public List<DateTime> holidays;
    [DataMember]
    public CityList cities;
    [DataMember]
    public ArrayList otherInfo;
}

public class Person
{
    public Person(string fName, string lName)
    {
        this.firstName = fName;
        this.lastName = lName;
    }

    public string firstName;
    public string lastName;
}

public class PeopleEnum : IEnumerator
{
    public Person[] _people;

    // Enumerators are positioned before the first element
    // until the first MoveNext() call.
    int position = -1;

    public PeopleEnum(Person[] list)
    {
        _people = list;
    }

    public bool MoveNext()
    {
        position++;
        return (position < _people.Length);
    }

    public void Reset()
    {
        position = -1;
    }

    public object Current
    {
        get
        {
            try
            {
                return _people[position];
            }
            catch (IndexOutOfRangeException)
            {
                throw new InvalidOperationException();
            }
        }
    }
}

[CollectionDataContract(Name = "Cities", ItemName = "city", KeyName = "cityName", ValueName = "population")]
public class CityList : IDictionary<string, int>, IEnumerable<System.Collections.Generic.KeyValuePair<string, int>>
{
    private Person[] _people = null;

    public bool ContainsKey(string s) { return true; }
    public bool Contains(string s) { return true; }
    public bool Contains(KeyValuePair<string, int> item) { return (true); }
    public void Add(string key, int value) { }
    public void Add(KeyValuePair<string, int> keykValue) { }
    public bool Remove(string s) { return true; }
    public bool TryGetValue(string d, out int i)
    {
        i = 0; return (true);
    }

    /*
    [TypeConverterAttribute(typeof(SynchronizationHandlesTypeConverter))]
    public ICollection<string> SynchronizationHandles {
        get { return (System.Collections.Generic.ICollection<string>) new Stack<string> (); }
        set { }
    }*/

    public ICollection<string> Keys
    {
        get
        {
            return (System.Collections.Generic.ICollection<string>)new Stack<string>();
        }
    }

    public int this[string s]
    {
        get
        {
            return 0;
        }
        set
        {
        }
    }

    public ICollection<int> Values
    {
        get
        {
            return (System.Collections.Generic.ICollection<int>)new Stack<string>();
        }
    }

    public void Clear() { }
    public void CopyTo(KeyValuePair<string, int>[] array, int index) { }
    public bool Remove(KeyValuePair<string, int> item) { return true; }
    public int Count { get { return 0; } }
    public bool IsReadOnly { get { return true; } }

    IEnumerator<KeyValuePair<string, int>>
        System.Collections.Generic.IEnumerable<System.Collections.Generic.KeyValuePair<string, int>>.GetEnumerator()
    {
        return (IEnumerator<KeyValuePair<string, int>>)new PeopleEnum(_people); ;
    }

    public IEnumerator GetEnumerator()
    {
        return new PeopleEnum(_people);
    }
}

<DataContract()>
Public Class CountryOrRegion

    <DataMember()>
    Public officialLanguages As Collection(Of String)

    <DataMember()>
    Public holidays As List(Of DateTime)

    <DataMember()>
    Public cities As CityList

    <DataMember()>
    Public otherInfo As ArrayList

End Class

Public Class Person
    Public Sub New(ByVal fName As String, ByVal lName As String)
        Me.firstName = fName
        Me.lastName = lName
    End Sub

    Public firstName As String
    Public lastName As String
End Class

Public Class PeopleEnum
    Implements IEnumerator

    Public _people() As Person
    ' Enumerators are positioned before the first element
    ' until the first MoveNext() call.
    Private position As Integer = -1

    Public Sub New(ByVal list() As Person)
        _people = list
    End Sub

    Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
        position += 1
        Return position < _people.Length
    End Function

    Public Sub Reset() Implements IEnumerator.Reset
        position = -1
    End Sub

    Public ReadOnly Property Current() As Object Implements IEnumerator.Current
        Get
            Try
                Return _people(position)
            Catch e1 As IndexOutOfRangeException
                Throw New InvalidOperationException()
            End Try
        End Get
    End Property
End Class

<CollectionDataContract(Name:="Cities",
                        ItemName:="city",
                        KeyName:="cityName",
                        ValueName:="population")>
Public Class CityList
    Implements IDictionary(Of String, Integer), IEnumerable(Of System.Collections.Generic.KeyValuePair(Of String, Integer))

    Private _people() As Person = Nothing

    Public Function ContainsKey(ByVal s As String) As Boolean Implements IDictionary(Of String, Integer).ContainsKey
        Return True
    End Function

    Public Function Contains(ByVal s As String) As Boolean
        Return True
    End Function

    Public Function Contains(ByVal item As KeyValuePair(Of String, Integer)) As Boolean Implements IDictionary(Of String, Integer).Contains
        Return (True)
    End Function

    Public Sub Add(ByVal key As String,
                   ByVal value As Integer) Implements IDictionary(Of String, Integer).Add
    End Sub

    Public Sub Add(ByVal keykValue As KeyValuePair(Of String, Integer)) Implements IDictionary(Of String, Integer).Add
    End Sub

    Public Function Remove(ByVal s As String) As Boolean Implements IDictionary(Of String, Integer).Remove
        Return True
    End Function

    Public Function TryGetValue(ByVal d As String,
                                <System.Runtime.InteropServices.Out()> ByRef i As Integer) _
                                As Boolean Implements IDictionary(Of String, Integer).TryGetValue
        i = 0
        Return (True)
    End Function

    Public ReadOnly Property Keys() As ICollection(Of String) Implements IDictionary(Of String, Integer).Keys
        Get
            Return CType(New Stack(Of String)(), System.Collections.Generic.ICollection(Of String))
        End Get
    End Property

    Default Public Property Item(ByVal s As String) As Integer Implements IDictionary(Of String, Integer).Item
        Get
            Return 0
        End Get
        Set(ByVal value As Integer)
        End Set
    End Property

    Public ReadOnly Property Values() As ICollection(Of Integer) Implements IDictionary(Of String, Integer).Values
        Get
            Return CType(New Stack(Of String)(), System.Collections.Generic.ICollection(Of Integer))
        End Get
    End Property

    Public Sub Clear() Implements IDictionary(Of String, Integer).Clear
    End Sub

    Public Sub CopyTo(ByVal array() As KeyValuePair(Of String, Integer),
                      ByVal index As Integer) Implements IDictionary(Of String, Integer).CopyTo
    End Sub

    Public Function Remove(ByVal item As KeyValuePair(Of String, Integer)) As Boolean Implements IDictionary(Of String, Integer).Remove
        Return True
    End Function

    Public ReadOnly Property Count() As Integer Implements IDictionary(Of String, Integer).Count
        Get
            Return 0
        End Get
    End Property

    Public ReadOnly Property IsReadOnly() As Boolean Implements IDictionary(Of String, Integer).IsReadOnly
        Get
            Return True
        End Get
    End Property

    Private Function IEnumerable_GetEnumerator() As IEnumerator(Of KeyValuePair(Of String, Integer)) _
        Implements System.Collections.Generic.IEnumerable(Of System.Collections.Generic.KeyValuePair(Of String, Integer)).GetEnumerator

        Return CType(New PeopleEnum(_people), IEnumerator(Of KeyValuePair(Of String, Integer)))
    End Function

    Public Function GetEnumerator() As IEnumerator Implements System.Collections.IEnumerable.GetEnumerator

        Return New PeopleEnum(_people)

    End Function

End Class

스키마를 내보내고 다시 가져올 때 생성된 클라이언트 코드는 다음과 유사합니다(읽기 용이한 속성 대신 필드가 표시됨).

[DataContract]
public class CountryOrRegion2
{
    [DataMember]
    public string[] officialLanguages;
    [DataMember]
    public DateTime[] holidays;
    [DataMember]
    public Cities cities;
    [DataMember]
    public object[] otherInfo;
}

[CollectionDataContract(ItemName = "city", KeyName = "cityName", ValueName = "population")]
public class Cities : Dictionary<string, int> { }
<DataContract()>
Public Class CountryOrRegion2
    <DataMember()>
    Public officialLanguages() As String
    <DataMember()>
    Public holidays() As DateTime
    <DataMember()>
    Public cities As Cities
    <DataMember()>
    Public otherInfo() As Object
End Class

<CollectionDataContract(ItemName:="city", KeyName:="cityName", ValueName:="population")>
Public Class Cities
    Inherits Dictionary(Of String, Integer)
End Class

생성된 코드에서 기본 형식과 다른 형식을 사용할 수 있습니다. 예를 들어 데이터 멤버를 사용자 인터페이스 구성 요소에 보다 쉽게 바인딩할 수 있도록 일반 배열 대신 제네릭 BindingList<T> 을 사용할 수 있습니다.

생성할 컬렉션 형식을 선택하려면 스키마를 가져올 때 사용할 컬렉션 형식 목록을 개체의 ReferencedCollectionTypes 속성에 ImportOptions 전달합니다. 이러한 형식을 참조된 컬렉션 형식이라고합니다.

제네릭 형식을 참조할 때는 완전히 열려 있는 제네릭이거나 완전히 닫힌 제네릭이어야 합니다.

비고

Svcutil.exe 도구를 사용하는 경우 /collectionType 명령줄 스위치(약식: /ct)를 사용하여 이 참조를 수행할 수 있습니다. /reference 스위치(약식: /r)를 사용하여 참조된 컬렉션 형식에 대한 어셈블리도 지정해야 합니다. 형식이 제네릭인 경우 뒤에 따옴표와 제네릭 매개 변수 수가 와야 합니다. 역따옴표(`)는 작은따옴표(‘) 문자와 혼동해서는 안 됩니다. /collectionType 스위치를 두 번 이상 사용하여 여러 참조된 컬렉션 형식을 지정할 수 있습니다.

예를 들어 모든 목록을 제네릭 List<T>으로 가져오도록 합니다.

svcutil.exe MyService.wsdl MyServiceSchema.xsd /r:C:\full_path_to_system_dll\System.dll /ct:System.Collections.Generic.List`1

컬렉션을 가져올 때 참조된 컬렉션 형식 목록이 검색되고, 데이터 멤버 형식(사용자 지정되지 않은 컬렉션의 경우) 또는 파생할 기본 형식(사용자 지정된 컬렉션의 경우)으로 검색되는 경우 가장 일치하는 컬렉션이 사용됩니다. 사전은 사전과만 일치하지만 목록은 목록과 일치합니다.

예를 들어 제네릭 BindingList<T>Hashtable 참조된 형식 목록에 추가하는 경우 앞의 예제에 대해 생성된 클라이언트 코드는 다음과 유사합니다.

[DataContract]
public class CountryOrRegion3
{
    [DataMember]
    public BindingList<string> officialLanguages;
    [DataMember]
    public BindingList<DateTime> holidays;
    [DataMember]
    public Cities cities;
    [DataMember]
    public BindingList<object> otherInfo;
}

[CollectionDataContract(ItemName = "city", KeyName = "cityName", ValueName = "population")]
public class Cities3 : Hashtable { }
<DataContract()>
Public Class CountryOrRegion3

    <DataMember()>
    Public officialLanguages As BindingList(Of String)

    <DataMember()>
    Public holidays As BindingList(Of DateTime)

    <DataMember()>
    Public cities As Cities

    <DataMember()>
    Public otherInfo As BindingList(Of Object)

End Class

<CollectionDataContract(ItemName:="city",
                        KeyName:="cityName",
                        ValueName:="population")>
Public Class Cities3
    Inherits Hashtable
End Class

참조된 컬렉션 형식의 일부로 컬렉션 인터페이스 형식을 지정할 수 있지만 잘못된 컬렉션 형식(예: 메서드 또는 공용 생성자가 없는 Add 형식)을 지정할 수는 없습니다.

닫힌 유형이 가장 적합한 것으로 간주됩니다. (제네릭이 아닌 형식은 닫힌 제네릭과 Object동일한 것으로 간주됩니다.) 예를 들어, List<T>DateTime과 같은 제네릭과 개방형 제네릭 BindingList<T>이 포함된 경우, 참조된 컬렉션 형식으로 ArrayList가 생성됩니다.

[DataContract]
public class CountryOrRegion4
{
    [DataMember]
    public string[] officialLanguages;
    [DataMember]
    public DateTime[] holidays;
    [DataMember]
    public Cities cities;
    [DataMember]
    public object[] otherInfo;
}

[CollectionDataContract(ItemName = "city", KeyName = "cityName", ValueName = "population")]
public class Cities4 : Dictionary<string, int> { }
<DataContract()>
Public Class CountryOrRegion4

    <DataMember()>
    Public officialLanguages() As String

    <DataMember()>
    Public holidays() As DateTime

    <DataMember()>
    Public cities As Cities

    <DataMember()>
    Public otherInfo() As Object

End Class

<CollectionDataContract(ItemName:="city",
                        KeyName:="cityName",
                        ValueName:="population")>
Public Class Cities4
    Inherits Dictionary(Of String, Integer)
End Class

목록 컬렉션의 경우 다음 표의 사례만 지원됩니다.

참조된 형식 참조된 형식으로 구현된 인터페이스 예시 형식이 다음과 같이 취급됩니다.
제네릭이 아니거나 닫힌 제네릭(매개 변수 수) 제네릭이 아닌 MyType : IList

또는

MyType<T> : IList

where T= int
닫힌 제네릭( Object 예: IList<object>)
제네릭이 아니거나 닫힌 제네릭(컬렉션 형식과 반드시 일치하지 않는 매개 변수 수) 폐쇄적 일반 상표 MyType : IList<string>

또는

MyType<T> : IList<string> where T=int
닫힌 제네릭(예: IList<string>)
아무 개수의 매개 변수를 가진 닫힌 제네릭 형식의 매개 변수 중 하나를 사용하여 제네릭 열기 MyType<T,U,V> : IList<U>

where T=int, U=string, V=bool
닫힌 제네릭(예: IList<string>)
하나의 매개 변수로 제네릭 열기 형식의 매개 변수를 사용하여 제네릭 열기 MyType<T> : IList<T>, T가 열려 있습니다. 제네릭 열기(예: IList<T>)

형식이 둘 이상의 목록 컬렉션 인터페이스를 구현하는 경우 다음 제한 사항이 적용됩니다.

  • 형식이 다른 형식에 대해 제네릭 IEnumerable<T> (또는 파생 인터페이스)을 여러 번 구현하는 경우 형식은 참조된 유효한 컬렉션 형식으로 간주되지 않으며 무시됩니다. 일부 구현이 잘못되었거나 개방형 제네릭을 사용하는 경우에도 마찬가지입니다. 예를 들어, IEnumerable<T>의 제네릭 int 및 T의 제네릭 IEnumerable<T>를 구현하는 형식은 int 메서드가 Add 형식을 허용하는지, T 형식의 매개 변수를 허용하는 int 메서드가 있는지, 또는 둘 다인지에 관계없이 Add 또는 다른 형식의 참조 컬렉션으로 사용되지 않습니다.

  • 형식이 제네릭 컬렉션 인터페이스와 IList를 구현하는 경우, 제네릭 컬렉션 인터페이스가 형식 Object의 특정화된 제네릭이 아니면 그 형식은 참조된 컬렉션 형식으로 사용되지 않습니다.

사전 컬렉션의 경우 다음 표의 사례만 지원됩니다.

참조된 형식 참조된 형식으로 구현된 인터페이스 예시 다음으로 처리되는 형식
제네릭이 아니거나 닫힌 제네릭(매개 변수 수) IDictionary MyType : IDictionary

또는

MyType<T> : IDictionary where T=int
닫힌 제네릭 IDictionary<object,object>
매개변수의 개수에 제한이 없는 제너릭 IDictionary<TKey,TValue>닫힘 MyType<T> : IDictionary<string, bool> where T=int 닫힌 제네릭(예: IDictionary<string,bool>)
매개변수의 개수에 제한이 없는 제너릭 제네릭 IDictionary<TKey,TValue>, 키 또는 값 중 하나가 닫혀 있고, 다른 하나는 열려 있으며 형식의 매개 변수 중 하나를 사용합니다. MyType<T,U,V> : IDictionary<string,V> where T=int, U=float,V=bool

또는

MyType<Z> : IDictionary<Z,bool> where Z=string
닫힌 제네릭(예: IDictionary<string,bool>)
매개변수의 개수에 제한이 없는 제너릭 제네릭 IDictionary<TKey,TValue>, 키와 값이 모두 열려 있고 각각 형식의 매개 변수 중 하나를 사용합니다. MyType<T,U,V> : IDictionary<V,U> where T=int, U=bool, V=string 닫힌 제네릭(예: IDictionary<string,bool>)
제네릭 열기(두 개의 매개 변수) 제네릭 IDictionary<TKey,TValue>, 열기, 형식의 제네릭 매개 변수를 모두 나타나는 순서대로 사용합니다. MyType<K,V> : IDictionary<K,V>, K 및 V 모두 열기 제네릭 열기(예: IDictionary<K,V>)

형식이 IDictionary 및 제네릭 IDictionary<TKey,TValue>을 모두 구현하는 경우, 제네릭 IDictionary<TKey,TValue>만 고려됩니다.

부분 제네릭 형식 참조는 지원되지 않습니다.

중복은 허용되지 않습니다. 예를 들어, List<T>의 제네릭 IntegerInteger의 제네릭 컬렉션을 ReferencedCollectionTypes에 둘 다 추가할 수 없습니다. 이는 스키마에서 정수 목록을 찾을 때 어느 것을 사용할지 결정할 수 없게 만듭니다. 중복 문제는 중복 문제를 노출하는 형식이 스키마에 있는 경우에만 검색됩니다. 예를 들어, 가져오는 스키마에 정수 목록이 포함되지 않은 경우 List<T>의 제네릭 IntegerInteger의 제네릭 컬렉션을 ReferencedCollectionTypes에 모두 포함할 수 있지만, 둘 다 아무런 영향을 미치지 않습니다.

고급 컬렉션 규칙

컬렉션 직렬화

다음은 serialization에 대한 컬렉션 규칙 목록입니다.

  • 컬렉션 형식(컬렉션의 모음 포함)을 결합할 수 있습니다. 가변 배열은 여러 컬렉션으로 처리됩니다. 다차원 배열은 지원되지 않습니다.

  • 바이트 배열과 배열 XmlNode 은 컬렉션이 아닌 기본 형식으로 처리되는 특수 배열 형식입니다. 바이트 배열을 직렬화하면 각 바이트에 대해 별도의 요소가 아닌 Base64로 인코딩된 데이터의 청크가 포함된 단일 XML 요소가 생성됩니다. 배열을 XmlNode 처리하는 방법에 대한 자세한 내용은 데이터 계약의 XML 및 ADO.NET 형식을 참조하세요. 물론 이러한 특수 형식은 자체 컬렉션에 참여할 수 있습니다. 바이트 배열의 배열은 각각 Base64로 인코딩된 데이터의 청크를 포함하는 여러 XML 요소를 생성합니다.

  • 특성이 DataContractAttribute 컬렉션 형식에 적용되는 경우 형식은 컬렉션이 아닌 일반 데이터 계약 형식으로 처리됩니다.

  • 컬렉션 형식이 IXmlSerializable 인터페이스를 구현하는 경우, 형식 myType:IList<string>, IXmlSerializable이 주어졌을 때 다음 규칙이 적용됩니다.

    • 선언된 형식이 IList<string>면 형식이 목록으로 serialize됩니다.

    • 선언된 형식이 myType인 경우, IXmlSerializable로 직렬화됩니다.

    • 선언된 형식이 IXmlSerializable인 경우, IXmlSerializable를 알려진 형식 목록에 추가한 후에만 myType로 직렬화됩니다.

  • 컬렉션은 다음 표에 표시된 메서드를 사용하여 직렬화되고 역직렬화됩니다.

컬렉션 형식 구현 직렬화에서 호출된 메서드(들) 역직렬화 시 호출된 메서드
일반적인 IDictionary<TKey,TValue> get_Keys, get_Values 일반 추가
IDictionary get_Keys, get_Values Add
일반적인 IList<T> 제네릭 IList<T> 인덱서 일반 추가
일반적인 ICollection<T> 열거자 일반 추가
IList IList 인덱서 Add
일반적인 IEnumerable<T> GetEnumerator 적절한 형식의 매개 변수(제네릭 매개 변수의 형식 또는 기본 형식 중 하나)를 사용하는 비정적 메서드입니다 Add . 직렬화 및 역직렬화 중에 컬렉션 형식을 컬렉션으로 처리하려면 serializer에 이러한 메서드가 있어야 합니다.
IEnumerable (따라서 ICollection에서 파생된) GetEnumerator 형식Add의 매개 변수 하나를 사용하는 비정적 메서드입니다Object. 직렬화 및 역직렬화 중에 컬렉션 형식을 컬렉션으로 처리하려면 serializer에 이러한 메서드가 있어야 합니다.

앞의 표에는 컬렉션 인터페이스가 우선 순위의 내림차순으로 나열되어 있습니다. 예를 들어, 타입이 IList 및 제네릭 IEnumerable<T>을 모두 구현하는 경우, 컬렉션은 IList 규칙에 따라 직렬화되고 역직렬화됩니다.

  • 역직렬화 시 모든 컬렉션은 먼저 매개 변수가 없는 생성자를 호출하여 형식의 인스턴스를 만들어 역직렬화됩니다. 이 생성자는 serialization 및 deserialization 중에 컬렉션 형식을 컬렉션으로 처리하기 위해 직렬 변환기에 있어야 합니다.

  • 동일한 제네릭 컬렉션 인터페이스가 여러 번 구현되는 경우(예를 들어, 형식이 Generic ICollection<T> of Integer 및 Generic ICollection<T> of String을 모두 구현하는 경우) 우선순위가 더 높은 인터페이스가 발견되지 않으면, 해당 컬렉션은 유효한 컬렉션으로 처리되지 않습니다.

  • 컬렉션 형식에는 SerializableAttribute 특성이 적용될 수 있으며, ISerializable 인터페이스를 구현할 수 있습니다. 이 두 가지 모두 무시됩니다. 그러나 형식이 컬렉션 형식 요구 사항을 완전히 충족하지 않는 경우(예 Add : 메서드가 누락된 경우) 형식은 컬렉션 형식 SerializableAttribute 으로 간주되지 않으므로 특성과 ISerializable 인터페이스를 사용하여 형식을 serialize할 수 있는지 여부를 확인합니다.

  • 특성을 컬렉션에 CollectionDataContractAttribute 적용하여 사용자 지정할 경우, 앞선 대체 메커니즘이 SerializableAttribute 제거됩니다. 대신 사용자 지정된 컬렉션이 컬렉션 형식 요구 사항을 충족하지 않으면 예외가 InvalidDataContractException throw됩니다. 예외 문자열에는 지정된 형식이 유효한 컬렉션(메서드 없음 Add , 매개 변수 없는 생성자 등)으로 간주되지 않는 이유를 설명하는 정보가 포함되어 있으므로 디버깅을 위해 특성을 적용 CollectionDataContractAttribute 하는 것이 유용한 경우가 많습니다.

컬렉션 이름 지정

다음은 컬렉션 명명 규칙 목록입니다.

  • 네임스페이스를 사용하여 재정의되지 않는 한, 모든 사전 컬렉션 데이터 계약과 기본 형식을 포함하는 목록 컬렉션 데이터 계약의 기본 네임스페이스는 http://schemas.microsoft.com/2003/10/Serialization/Arrays입니다. 기본 제공 XSD 형식 및 charTimespanGuid 형식에 매핑되는 형식은 이러한 용도로 기본 형식으로 간주됩니다.

  • 네임스페이스를 사용하여 재정의되지 않는 한 기본 형식이 아닌 형식을 포함하는 컬렉션 형식의 기본 네임스페이스는 컬렉션에 포함된 형식의 데이터 계약 네임스페이스와 동일합니다.

  • Name을 사용하여 재정의하지 않는 한 목록 컬렉션 데이터 계약의 기본 이름은 컬렉션에 포함된 형식의 데이터 계약 이름과 결합된 문자열 "ArrayOf"입니다. 예를 들어 정수의 제네릭 목록에 대한 데이터 계약 이름은 "ArrayOfint"입니다. 데이터 계약 이름은 Object "anyType"이므로 제네릭이 아닌 목록 ArrayList 의 데이터 계약 이름은 "ArrayOfanyType"입니다.

사전 컬렉션 데이터 계약의 기본 이름은 Name으로 덮어쓰지 않는 한, "ArrayOfKeyValueOf" 문자열과 키 유형의 데이터 계약 이름, 그리고 값 유형의 데이터 계약 이름이 결합된 문자열입니다. 예를 들어 문자열 및 정수 제네릭 사전의 데이터 계약 이름은 "ArrayOfKeyValueOfstringint"입니다. 또한 키 또는 값 형식이 기본 형식이 아닌 경우 키 및 값 형식의 데이터 계약 네임스페이스의 네임스페이스 해시가 이름에 추가됩니다. 네임스페이스 해시에 대한 자세한 내용은 데이터 계약 이름을 참조하세요.

각 사전 컬렉션 데이터 계약에는 사전의 한 항목을 나타내는 도우미 데이터 계약이 있습니다. 해당 이름은 "ArrayOf" 접두사를 제외하고 사전 데이터 계약과 동일하며 해당 네임스페이스는 사전 데이터 계약과 동일합니다. 예를 들어 "ArrayOfKeyValueOfstringint" 사전 데이터 계약의 경우 "KeyValueofstringint" 데이터 계약은 사전의 한 항목을 나타냅니다. 다음 섹션에 설명된 대로 속성을 사용하여 ItemName 이 데이터 계약의 이름을 사용자 지정할 수 있습니다.

데이터 계약 이름에 설명된 제네릭 형식 명명 규칙은 컬렉션 형식에 완전히 적용됩니다. 즉, Name 내에서 중괄호를 사용하여 제네릭 형식 매개 변수를 나타낼 수 있습니다. 그러나 중괄호 내의 숫자는 컬렉션에 포함된 형식이 아니라 제네릭 매개 변수를 참조합니다.

컬렉션 사용자 지정

다음과 같은 특성 사용 CollectionDataContractAttribute 이 금지되어 예외가 발생합니다 InvalidDataContractException .

다형성 규칙

앞에서 설명한 것처럼 특성을 사용하여 CollectionDataContractAttribute 컬렉션을 사용자 지정하면 컬렉션의 교환성을 방해할 수 있습니다. 사용자 지정된 두 컬렉션 형식은 이름, 네임스페이스, 항목 이름, 키 및 값 이름(사전 컬렉션인 경우)이 일치하는 경우에만 동등한 것으로 간주할 수 있습니다.

사용자 지정으로 인해 실수로 한 컬렉션 데이터 계약을 다른 예상된 데이터 계약으로 잘못 사용할 수 있습니다. 이 작업은 피해야 합니다. 다음 형식을 참조하세요.

[DataContract]
public class Student
{
    [DataMember]
    public string name;
    [DataMember]
    public IList<int> testMarks;
}
public class Marks1 : List<int> {}
[CollectionDataContract(ItemName="mark")]
public class Marks2 : List<int> {}
<DataContract()>
Public Class Student

    <DataMember()>
    Public name As String

    <DataMember()>
    Public testMarks As IList(Of Integer)

End Class

Public Class Marks1
    Inherits List(Of Integer)
End Class

<CollectionDataContract(ItemName:="mark")>
Public Class Marks2
    Inherits List(Of Integer)
End Class

이 경우 Marks1의 인스턴스를 testMarks에 할당할 수 있습니다. 그러나 Marks2 데이터 계약이 데이터 계약과 동등한 IList<int> 것으로 간주되지 않으므로 사용하면 안 됩니다. 데이터 계약 이름은 "ArrayOfint"가 아닌 "Marks2"이고 반복 요소 이름은 "int<"가 아닌 "><mark>"입니다.

다음 표의 규칙은 컬렉션의 다형 할당에 적용됩니다.

선언된 형식 사용자 지정되지 않은 컬렉션 할당 사용자 지정된 컬렉션 할당
객체 계약 이름이 직렬화됩니다. 계약 이름이 직렬화됩니다.

사용자 지정이 사용됩니다.
컬렉션 인터페이스 계약 이름이 직렬화되지 않았습니다. 계약 이름이 직렬화되지 않았습니다.

사용자 지정이 사용되지 않습니다.*
사용자 지정되지 않은 컬렉션 계약 이름이 직렬화되지 않았습니다. 계약 이름이 직렬화됩니다.

사용자 지정이 사용됩니다.**
사용자 지정된 컬렉션 계약 이름이 직렬화됩니다. 사용자 지정이 사용되지 않습니다.** 계약 이름이 직렬화됩니다.

할당된 형식의 사용자 지정이 사용됩니다.**

이 경우 NetDataContractSerializer 클래스에서 사용자 지정을 사용합니다. 또한 이 경우 클래스는 NetDataContractSerializer 실제 형식 이름을 직렬화하므로 역직렬화가 예상대로 작동합니다.

**이러한 경우 스키마가 잘못된 인스턴스가 발생하므로 피해야 합니다.

계약 이름이 serialize되는 경우 할당된 컬렉션 형식은 알려진 형식 목록에 있어야 합니다. 그 반대의 경우도 마찬가지입니다. 이름이 serialize되지 않은 경우 알려진 형식 목록에 형식을 추가할 필요가 없습니다.

파생 형식의 배열을 기본 형식의 배열에 할당할 수 있습니다. 이 경우 파생 형식의 계약 이름은 반복되는 각 요소에 대해 serialize됩니다. 예를 들어, Book 형식이 LibraryItem 형식에서 파생된 경우, Book 배열을 LibraryItem 배열에 할당할 수 있습니다. 다른 컬렉션 형식에는 적용되지 않습니다. 예를 들어, Generic List of BookGeneric List of LibraryItem에 할당할 수 없습니다. 인스턴스를 포함하는 Generic List of LibraryItem 항목을 Book에 할당할 수 있습니다. 배열과 배열이 아닌 경우 Book 모두 알려진 형식 목록에 있어야 합니다.

컬렉션 및 개체 참조 유지

직렬 변환기가 개체 참조를 유지하는 모드에서 작동하는 경우 개체 참조 보존도 컬렉션에 적용됩니다. 특히 개체 ID는 전체 컬렉션과 컬렉션에 포함된 개별 항목 모두에 대해 유지됩니다. 사전의 경우 키/값 쌍 개체와 개별 키 및 값 개체 모두에 대해 개체 ID가 유지됩니다.

참고하십시오