Bagikan melalui


Jenis Koleksi dalam Kontrak Data

Koleksi adalah daftar item dari jenis tertentu. Di .NET Framework, daftar tersebut dapat diwakili menggunakan array atau berbagai jenis lainnya (Daftar Generik, Generik BindingList<T>, StringCollection, atau ArrayList). Misalnya, koleksi dapat menyimpan daftar Alamat untuk Pelanggan tertentu. Koleksi ini disebut koleksi daftar, terlepas dari jenisnya yang sebenarnya.

Ada bentuk koleksi khusus yang mewakili hubungan antara satu item ("kunci") dan yang lain ("nilai"). Di .NET Framework, ini diwakili oleh jenis seperti Hashtable dan kamus generik. Misalnya, koleksi asosiasi dapat memetakan kota ("kunci") ke populasinya ("nilai"). Koleksi ini disebut koleksi kamus, terlepas dari jenisnya yang sebenarnya.

Koleksi menerima perlakuan khusus dalam model kontrak data.

Jenis yang mengimplementasikan antarmuka IEnumerable, termasuk array dan koleksi generik, dikenali sebagai koleksi. Dari koleksi tersebut, jenis yang mengimplementasikan IDictionary atau Antarmuka IDictionary<TKey,TValue> generik adalah koleksi kamus; yang lain adalah koleksi daftar.

Persyaratan tambahan tentang jenis koleksi, seperti memiliki metode yang disebut Add dan konstruktor tanpa parameter, dibahas secara rinci di bagian berikut. Ini memastikan bahwa jenis koleksi dapat diserialisasikan dan dideserialisasi. Ini berarti bahwa beberapa koleksi tidak didukung secara langsung, seperti ReadOnlyCollection<T> generik (karena tidak memiliki konstruktor tanpa parameter). Namun, untuk informasi tentang menghindari pembatasan ini, lihat bagian "Menggunakan Jenis Antarmuka Koleksi dan Koleksi Baca-Saja" nanti dalam topik ini.

Jenis yang terkandung dalam koleksi harus berupa jenis kontrak data, atau jenis yang dapat diserialisasikan. Untuk mengetahui informasi selengkapnya, lihat Jenis yang Didukung oleh Serializer Kontrak Data.

Untuk mengetahui informasi selengkapnya tentang apa itu dan apa yang tidak dianggap sebagai koleksi yang valid, serta tentang cara koleksi diserialisasikan, lihat informasi tentang serialisasi koleksi di bagian "Aturan Koleksi Tingkat Lanjut" dari topik ini.

Koleksi yang Dapat Dipertukarkan

Semua koleksi daftar dengan jenis yang sama dianggap memiliki kontrak data yang sama (kecuali jika disesuaikan menggunakan atribut CollectionDataContractAttribute, seperti yang dibahas nanti dalam topik ini). Dengan demikian, misalnya, kontrak data berikut setara.

[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

Kedua kontrak data menghasilkan XML yang mirip dengan kode berikut.

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

Pertukaran koleksi memungkinkan Anda menggunakan, misalnya, jenis koleksi yang dioptimalkan untuk performa di server dan jenis koleksi yang dirancang untuk terikat pada komponen antarmuka pengguna pada klien.

Mirip dengan koleksi daftar, semua koleksi kamus yang memiliki jenis kunci dan nilai yang sama dianggap memiliki kontrak data yang sama (kecuali disesuaikan oleh atribut CollectionDataContractAttribute).

Hanya jenis kontrak data yang penting sejauh menyangkut kesetaraan pengumpulan, bukan jenis .NET. Artinya, koleksi Type1 dianggap setara dengan koleksi Type2 jika Type1 dan Type2 memiliki kontrak data yang setara.

Koleksi non-generik dianggap memiliki kontrak data yang sama dengan koleksi generik jenis Object. (Misalnya, kontrak data untuk ArrayList dan List<T> generik dari Object sama.)

Menggunakan Jenis Antarmuka Koleksi dan Koleksi Baca-Saja

Jenis antarmuka koleksi (IEnumerable, IDictionary, IDictionary<TKey,TValue> generik, atau antarmuka yang berasal dari antarmuka ini) juga dianggap memiliki kontrak data pengumpulan, setara dengan kontrak data pengumpulan untuk jenis koleksi aktual. Dengan demikian, dimungkinkan untuk menyatakan jenis yang diserialisasikan sebagai jenis antarmuka koleksi dan hasilnya sama seolah-olah jenis koleksi aktual telah digunakan. Misalnya, kontrak data berikut setara.

[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

Selama serialisasi, jika jenis yang dideklarasikan adalah antarmuka, jenis instans aktual yang digunakan dapat berupa jenis apa pun yang mengimplementasikan antarmuka tersebut. Pembatasan yang dibahas sebelumnya (memiliki konstruktor tanpa parameter dan metode Add) tidak berlaku. Misalnya, Anda dapat mengatur alamat di Customer2 ke instans ReadOnlyCollection<T> generik Alamat, meskipun Anda tidak dapat secara langsung mendeklarasikan anggota data dari jenis ReadOnlyCollection<T> generik.

Selama deserialisasi, jika jenis yang dinyatakan adalah antarmuka, mesin serialisasi memilih jenis yang mengimplementasikan antarmuka yang dideklarasikan, dan jenisnya dibuat. Mekanisme jenis yang diketahui (dijelaskan dalam Kontrak Data Jenis yang Diketahui) tidak berpengaruh di sini; pilihan jenis dibangun ke dalam WCF.

Menyesuaikan Jenis Koleksi

Anda dapat menyesuaikan jenis koleksi dengan menggunakan atribut CollectionDataContractAttribute, yang memiliki beberapa penggunaan.

Perhatikan bahwa menyesuaikan jenis koleksi mengorbankan pertukaran koleksi, sehingga umumnya disarankan untuk menghindari penerapan atribut ini jika memungkinkan. Untuk mengetahui informasi selengkapnya tentang masalah ini, lihat bagian "Aturan Koleksi Tingkat Lanjut" nanti dalam topik ini.

Penamaan Kontrak Data Koleksi

Aturan untuk penamaan jenis koleksi mirip dengan aturan untuk penamaan jenis kontrak data reguler, seperti yang dijelaskan dalam Nama Kontrak Data, meskipun ada beberapa perbedaan penting:

  • Atribut CollectionDataContractAttribute digunakan untuk menyesuaikan nama, bukan atribut DataContractAttribute. Atribut CollectionDataContractAttribute juga memiliki properti Name dan Namespace.

  • Saat atribut CollectionDataContractAttribute tidak diterapkan, nama default dan namespace untuk jenis koleksi bergantung pada nama dan namespace jenis yang terkandung dalam koleksi. Jenis ini tidak terpengaruh oleh nama dan namespace dari jenis koleksi itu sendiri. Misalnya, lihat jenis berikut.

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

Nama kontrak data kedua jenis adalah "ArrayOfstring" dan bukan "CustomerList1" atau "StringList1". Ini berarti bahwa menserialisasikan salah satu jenis ini di tingkat akar menghasilkan XML yang mirip dengan kode berikut.

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

Aturan penamaan ini dipilih untuk memastikan bahwa jenis yang tidak disesuaikan yang mewakili daftar string memiliki kontrak data dan representasi XML yang sama. Ini memungkinkan pertukaran koleksi. Dalam contoh ini, CustomerList1 dan StringList1 sepenuhnya dapat dipertukarkan.

Namun, jika atribut CollectionDataContractAttribute diterapkan, koleksi menjadi kontrak data koleksi yang disesuaikan, meskipun tidak ada properti yang diatur pada atribut. Nama dan namespace kontrak data koleksi kemudian bergantung pada jenis koleksi itu sendiri. Misalnya, lihat jenis berikut.

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

Saat diserialisasikan, XML yang dihasilkan mirip dengan yang berikut ini.

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

Perhatikan bahwa ini tidak lagi setara dengan representasi XML dari jenis yang tidak disesuaikan.

  • Anda dapat menggunakan properti Name dan Namespace untuk menyesuaikan penamaan lebih lanjut. Lihat kelas berikut.

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

XML yang dihasilkan mirip dengan yang berikut ini.

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

Untuk mengetahui informasi selengkapnya, lihat bagian "Aturan Koleksi Tingkat Lanjut" nanti dalam topik ini.

Menyesuaikan Nama Elemen Berulang dalam Koleksi Daftar

Koleksi daftar berisi entri berulang. Biasanya, setiap entri berulang direpresentasikan sebagai elemen bernama sesuai dengan nama kontrak data dari jenis yang terkandung dalam koleksi.

Dalam contoh CustomerList, koleksi berisi string. Nama kontrak data untuk jenis primitif string adalah "string", sehingga elemen berulang adalah "<string>".

Namun, menggunakan properti ItemName pada atribut CollectionDataContractAttribute, nama elemen berulang ini dapat disesuaikan. Misalnya, lihat jenis berikut.

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

XML yang dihasilkan mirip dengan yang berikut ini.

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

Namespace elemen berulang selalu sama dengan namespace kontrak data pengumpulan, yang dapat disesuaikan menggunakan properti Namespace, seperti yang dijelaskan sebelumnya.

Menyesuaikan Koleksi Kamus

Koleksi kamus pada dasarnya adalah daftar entri, yang mana setiap entri memiliki kunci yang diikuti oleh nilai. Sama seperti daftar reguler, Anda dapat mengubah nama elemen yang sesuai dengan elemen berulang dengan menggunakan properti ItemName.

Selain itu, Anda dapat mengubah nama elemen yang mewakili kunci dan nilai dengan menggunakan properti KeyName dan ValueName. Namespace untuk elemen-elemen ini sama dengan namespace kontrak data koleksi.

Misalnya, lihat jenis berikut.

[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

Saat diserialisasikan, XML yang dihasilkan mirip dengan yang berikut ini.

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

Untuk mengetahui informasi selengkapnya tentang koleksi kamus, lihat bagian "Aturan Koleksi Tingkat Lanjut" nanti dalam topik ini.

Koleksi dan Jenis yang Diketahui

Anda tidak perlu menambahkan jenis koleksi ke jenis yang diketahui saat digunakan secara polimorfik sebagai pengganti koleksi atau antarmuka koleksi lainnya. Misalnya, jika mendeklarasikan anggota data jenis IEnumerable dan menggunakannya untuk mengirim instans ArrayList, Anda tidak perlu menambahkan ArrayList ke jenis yang diketahui.

Saat Anda menggunakan koleksi secara polimorfik sebagai pengganti jenis non-koleksi, koleksi harus ditambahkan ke jenis yang diketahui. Misalnya, jika Anda mendeklarasikan anggota data jenis Object dan menggunakannya untuk mengirim instans ArrayList, tambahkan ArrayList ke jenis yang diketahui.

Ini tidak memungkinkan Anda menserialisasikan koleksi yang setara secara polimorfik. Misalnya, jika Anda menambahkan ArrayList ke daftar jenis yang diketahui dalam contoh sebelumnya, ini tidak memungkinkan Anda menetapkan kelas Array of Object, meskipun memiliki kontrak data yang setara. Ini tidak berbeda dari perilaku jenis umum yang diketahui pada serialisasi untuk jenis non-koleksi, tetapi sangat penting untuk dipahami dalam kasus koleksi karena sangat umum untuk koleksi setara.

Selama serialisasi, hanya satu jenis yang dapat diketahui dalam cakupan tertentu untuk kontrak data tertentu, dan koleksi yang setara semuanya memiliki kontrak data yang sama. Ini berarti bahwa, dalam contoh sebelumnya, Anda tidak dapat menambahkan ArrayList dan Array of Object ke jenis yang diketahui pada cakupan yang sama. Sekali lagi, ini setara dengan perilaku jenis yang diketahui untuk jenis non-koleksi, tetapi sangat penting untuk dipahami untuk koleksi.

Jenis yang diketahui mungkin juga diperlukan untuk konten koleksi. Misalnya, jika ArrayList sebenarnya berisi instans Type1 dan Type2, kedua jenis ini harus ditambahkan ke jenis yang diketahui.

Contoh berikut menunjukkan grafik objek yang dibangun dengan benar menggunakan koleksi dan jenis yang diketahui. Contohnya agak diperjuangkan, karena dalam aplikasi aktual Anda biasanya tidak akan menentukan anggota data berikut sebagai Object, dan dengan demikian tidak memiliki masalah jenis/polimorfisme yang diketahui.

[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

Pada deserialisasi, jika jenis yang dinyatakan adalah jenis koleksi, jenis yang dinyatakan dibuat terlepas dari jenis yang benar-benar dikirim. Jika jenis yang dideklarasikan adalah antarmuka koleksi, deserializer memilih jenis yang akan dibuat tanpa memperhatikan jenis yang diketahui.

Juga pada deserialisasi, jika jenis yang dinyatakan bukan jenis koleksi tetapi jenis koleksi sedang dikirim, jenis koleksi yang cocok dipilih dari daftar jenis yang diketahui. Dimungkinkan untuk menambahkan jenis antarmuka koleksi ke daftar jenis yang diketahui pada deserialisasi. Dalam hal ini, mesin deserialisasi kembali memilih jenis yang akan dibuat.

Koleksi dan Kelas NetDataContractSerializer

Saat kelas NetDataContractSerializer sedang digunakan, jenis koleksi yang tidak disesuaikan (tanpa atribut CollectionDataContractAttribute) yang bukan array kehilangan arti khususnya.

Jenis koleksi yang tidak disesuaikan yang ditandai dengan atribut SerializableAttribute masih dapat diserialisasikan oleh kelas NetDataContractSerializer sesuai dengan atribut SerializableAttribute atau aturan antarmuka ISerializable.

Jenis koleksi, antarmuka koleksi, dan array yang disesuaikan masih diperlakukan sebagai koleksi, bahkan saat kelas NetDataContractSerializer sedang digunakan.

Koleksi dan Skema

Semua koleksi yang setara memiliki representasi yang sama dalam skema bahasa Definisi skema XML (XSD). Karena itu, Anda biasanya tidak mendapatkan jenis koleksi yang sama dalam kode klien yang dihasilkan dengan yang ada di server. Misalnya, server dapat menggunakan kontrak data dengan List<T> generik anggota data Bilangan Bulat, tetapi dalam kode klien yang dihasilkan, anggota data yang sama dapat menjadi array bilangan bulat.

Koleksi kamus ditandai dengan anotasi skema khusus WCF yang menunjukkan bahwa koleksi tersebut adalah kamus; jika tidak, koleksi tidak dapat dibedakan dari daftar sederhana yang berisi entri dengan kunci dan nilai. Untuk deskripsi yang tepat tentang cara koleksi diwakili dalam skema kontrak data, lihat Referensi Skema Kontrak Data.

Secara default, jenis tidak dihasilkan untuk koleksi yang tidak disesuaikan dalam kode yang diimpor. Anggota data dari jenis kumpulan daftar diimpor sebagai array, dan anggota data dari jenis koleksi kamus diimpor sebagai Kamus Generik.

Namun, untuk koleksi yang disesuaikan, jenis terpisah dihasilkan, ditandai dengan atribut CollectionDataContractAttribute. (Jenis koleksi yang disesuaikan dalam skema adalah jenis yang tidak menggunakan namespace default, nama, nama elemen berulang, atau nama elemen kunci/nilai.) Jenis ini adalah jenis kosong yang berasal dari List<T> generik untuk jenis daftar dan Kamus Generik untuk jenis kamus.

Misalnya, Anda mungkin memiliki jenis berikut di server.

[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

Jika skema diekspor dan diimpor kembali, kode klien yang dihasilkan mirip dengan yang berikut ini (bidang ditampilkan alih-alih properti untuk kemudahan membaca).

[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

Anda mungkin ingin menggunakan berbagai jenis dalam kode yang dihasilkan daripada yang default. Misalnya, Anda mungkin ingin menggunakan BindingList<T> generik alih-alih array reguler untuk anggota data Anda untuk mempermudah mengikatnya ke komponen antarmuka pengguna.

Untuk memilih jenis koleksi yang akan dihasilkan, berikan daftar jenis koleksi yang ingin Anda gunakan ke properti ReferencedCollectionTypes objek ImportOptions saat mengimpor skema. Jenis ini disebut jenis koleksi yang dirujuk.

Saat jenis generik dirujuk, jenis tersebut harus berupa generik yang terbuka sepenuhnya atau generik yang sepenuhnya tertutup.

Catatan

Saat menggunakan alat Svcutil.exe, referensi ini dapat dicapai dengan menggunakan tombol baris perintah /collectionType (bentuk pendek: /ct). Perlu diingat bahwa Anda juga harus menentukan rakitan untuk jenis koleksi yang dirujuk menggunakan tombol /reference (bentuk pendek: /r). Jika jenisnya generik, jenis tersebut harus diikuti dengan tanda petik balik dan jumlah parameter generik. Tanda petik balik (') tidak sama dengan karakter tanda petik tunggal ('). Anda dapat menentukan beberapa jenis koleksi yang dirujuk dengan menggunakan tombol /collectionType lebih dari sekali.

Misalnya, agar semua daftar diimpor sebagai List<T> generik.

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

Saat mengimpor koleksi apa pun, daftar jenis koleksi yang direferensikan ini dipindai, dan koleksi yang paling cocok digunakan jika ditemukan, baik sebagai jenis anggota data (untuk koleksi yang tidak disesuaikan) atau sebagai jenis dasar tempat asal (untuk koleksi yang disesuaikan). Kamus hanya dicocokkan dengan kamus, sementara daftar dicocokkan dengan daftar.

Misalnya, jika Anda menambahkan BindingList<T> dan Hashtable generik ke daftar jenis yang direferensikan, kode klien yang dihasilkan untuk contoh sebelumnya mirip dengan yang berikut ini.

[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

Anda dapat menentukan jenis antarmuka koleksi sebagai bagian dari jenis koleksi yang dirujuk, tetapi Anda tidak dapat menentukan jenis koleksi yang tidak valid (seperti yang tanpa metode Add atau konstruktor publik).

Generik tertutup dianggap sebagai kecocokan terbaik. (Jenis non-generik dianggap setara dengan generik tertutup Object). Misalnya, jika jenis List<T> generik dari DateTime, BindingList<T> generik (generik terbuka), dan ArrayList merupakan jenis koleksi yang dirujuk, berikut ini dihasilkan.

[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

Untuk kumpulan daftar, hanya kasus dalam tabel berikut yang didukung.

Jenis yang dirujuk Antarmuka yang diimplementasikan oleh jenis yang direferensikan Contoh Jenis diperlakukan sebagai:
Generik non-generik atau tertutup (sejumlah parameter) Non-generik MyType : IList

or

MyType<T> : IList

yang mana T= int
Generik tertutup Object (misalnya, IList<object>)
Generik non-generik atau tertutup (sejumlah parameter yang tidak selalu cocok dengan jenis koleksi) Generik tertutup MyType : IList<string>

or

MyType<T> : IList<string> yang mana T=int
Generik tertutup (misalnya, IList<string>)
Generik tertutup dengan sejumlah parameter Membuka generik menggunakan salah satu parameter jenis MyType<T,U,V> : IList<U>

yang mana T=int, U=string, V=bool
Generik tertutup (misalnya, IList<string>)
Membuka generik dengan satu parameter Membuka generik menggunakan parameter jenis MyType<T> : IList<T>, T terbuka Generik terbuka (misalnya, IList<T>)

Jika jenis mengimplementasikan lebih dari satu antarmuka koleksi daftar, pembatasan berikut berlaku:

  • Jika jenis mengimplementasikan IEnumerable<T> generik (atau antarmuka turunannya) beberapa kali untuk jenis yang berbeda, jenis tersebut tidak dianggap sebagai jenis koleksi yang dirujuk yang valid dan diabaikan. Ini berlaku meskipun beberapa implementasi tidak valid atau menggunakan generik terbuka. Misalnya, jenis yang mengimplementasikan IEnumerable<T> generik dari int dan IEnumerable<T> generik dari T tidak akan pernah digunakan sebagai koleksi yang dirujuk dari int atau jenis lainnya, terlepas dari apakah jenis tersebut memiliki metode Add yang menerima int atau metode Add yang menerima parameter jenis T, atau keduanya.

  • Jika jenis mengimplementasikan antarmuka koleksi generik serta IList, jenisnya tidak pernah digunakan sebagai jenis koleksi yang dirujuk kecuali antarmuka koleksi generik adalah generik tertutup dari jenis Object.

Untuk koleksi kamus, hanya kasus dalam tabel berikut yang didukung.

Jenis yang dirujuk Antarmuka yang diimplementasikan oleh jenis yang direferensikan Contoh Jenis diperlakukan sebagai
Generik non-generik atau tertutup (sejumlah parameter) IDictionary MyType : IDictionary

or

MyType<T> : IDictionary yang mana T=int
IDictionary<object,object> generik tertutup
Generik tertutup (sejumlah parameter) IDictionary<TKey,TValue>, tertutup MyType<T> : IDictionary<string, bool> yang mana T=int Generik tertutup (misalnya, IDictionary<string,bool>)
Generik tertutup (sejumlah parameter) IDictionary<TKey,TValue> generik, salah satu kunci atau nilai tertutup, yang lain terbuka dan menggunakan salah satu parameter jenis MyType<T,U,V> : IDictionary<string,V> yang mana T=int, U=float,V=bool

or

MyType<Z> : IDictionary<Z,bool> yang mana Z=string
Generik tertutup (Misalnya, IDictionary<string,bool>)
Generik tertutup (sejumlah parameter) IDictionary<TKey,TValue> generik, baik kunci maupun nilai terbuka dan masing-masing menggunakan salah satu parameter jenis MyType<T,U,V> : IDictionary<V,U> yang mana T=int, U=bool,V=string Generik tertutup (misalnya, IDictionary<string,bool>)
Generik terbuka (dua parameter) IDictionary<TKey,TValue> generik, terbuka, menggunakan kedua parameter generik jenis dalam urutan munculnya MyType<K,V> : IDictionary<K,V>, K dan V terbuka Generik terbuka (misalnya, IDictionary<K,V>)

Jika jenis mengimplementasikan IDictionary dan IDictionary<TKey,TValue> generik, hanya IDictionary<TKey,TValue> generik yang dipertimbangkan.

Mereferensikan jenis generik parsial tidak didukung.

Duplikat tidak diperbolehkan, misalnya, Anda tidak dapat menambahkan List<T> generik dari Integer dan Koleksi Generik Integer hingga ReferencedCollectionTypes, karena ini membuat tidak mungkin untuk menentukan mana yang akan digunakan saat daftar bilangan bulat ditemukan dalam skema. Duplikat terdeteksi hanya jika ada jenis dalam skema yang mengekspos masalah duplikat. Misalnya, jika skema yang diimpor tidak berisi daftar bilangan bulat, skema tersebut diizinkan untuk memiliki List<T> generik dari Integer dan Koleksi Generik Integer dalam ReferencedCollectionTypes, tetapi tidak memiliki efek apa pun.

Aturan Koleksi Tingkat Lanjut

Serialisasi Koleksi

Berikut ini adalah daftar aturan koleksi untuk serialisasi:

  • Menggabungkan jenis koleksi (memiliki koleksi) diperbolehkan. Array berjajar diperlakukan sebagai koleksi untuk koleksi. Array multidimensi tidak didukung.

  • Array byte dan array XmlNode adalah jenis array khusus yang diperlakukan sebagai primitif, bukan koleksi. Serialisasi array byte menghasilkan satu elemen XML yang berisi potongan data yang dikodekan Base64, alih-alih elemen terpisah untuk setiap byte. Untuk mengetahui informasi selengkapnya tentang cara array XmlNode diperlakukan, lihat Jenis XML dan ADO.NET dalam Kontrak Data. Tentu saja, jenis khusus ini sendiri dapat berpartisipasi dalam koleksi: array dari array byte menghasilkan beberapa elemen XML, dengan masing-masing berisi potongan data yang dikodekan Base64.

  • Jika atribut DataContractAttribute diterapkan ke jenis koleksi, jenis diperlakukan sebagai jenis kontrak data biasa, bukan sebagai koleksi.

  • Jika jenis koleksi mengimplementasikan antarmuka IXmlSerializable, aturan berikut berlaku, diberikan jenis myType:IList<string>, IXmlSerializable:

    • Jika jenis yang dinyatakan adalah IList<string>, jenis diserialisasikan sebagai daftar.

    • Jika jenis yang dinyatakan adalah myType, jenis diserialisasikan sebagai IXmlSerializable.

    • Jika jenis yang dinyatakan adalah IXmlSerializable, jenis diserialisasikan sebagai IXmlSerializable, tetapi hanya jika Anda menambahkan myType ke daftar jenis yang diketahui.

  • Koleksi diserialisasikan dan dideserialisasi menggunakan metode yang diperlihatkan dalam tabel berikut.

Jenis koleksi mengimplementasikan Metode yang dipanggil pada serialisasi Metode yang dipanggil pada deserialisasi
IDictionary<TKey,TValue> generik get_Keys, get_Values Penambahan Generik
IDictionary get_Keys, get_Values Add
IList<T> generik Pengindeks IList<T> generik Penambahan Generik
ICollection<T> generik Enumerator Penambahan Generik
IList Pengindeks IList Add
IEnumerable<T> generik GetEnumerator Metode non-statis yang disebut Add yang mengambil satu parameter dari jenis yang sesuai (jenis parameter generik atau salah satu jenis dasarnya). Metode seperti itu harus ada agar serializer memperlakukan jenis koleksi sebagai koleksi selama serialisasi dan deserialisasi.
IEnumerable (dan dengan demikian ICollection, yang berasal darinya) GetEnumerator Metode non-statis yang disebut Add yang mengambil satu parameter jenis Object. Metode seperti itu harus ada agar serializer memperlakukan jenis koleksi sebagai koleksi selama serialisasi dan deserialisasi.

Tabel sebelumnya mencantumkan antarmuka koleksi dalam urutan prioritas turun. Ini berarti, misalnya, bahwa jika jenis mengimplementasikan IList dan IEnumerable<T> generik, koleksi diserialisasikan dan dideserialisasi sesuai dengan aturan IList:

  • Pada deserialisasi, semua koleksi dideserialisasi dengan terlebih dahulu membuat instans jenis dengan memanggil konstruktor tanpa parameter, yang harus ada agar serializer memperlakukan jenis koleksi sebagai koleksi selama serialisasi dan deserialisasi.

  • Jika antarmuka koleksi generik yang sama diimplementasikan lebih dari sekali (misalnya, jika jenis mengimplementasikan ICollection<T> generik dari Integer dan ICollection<T> generik dari String) dan tidak ada antarmuka prioritas yang lebih tinggi yang ditemukan, koleksi tidak diperlakukan sebagai koleksi yang valid.

  • Jenis koleksi dapat memiliki atribut SerializableAttribute yang diterapkan padanya dan dapat mengimplementasikan antarmuka ISerializable. Keduanya diabaikan. Namun, jika jenis tidak sepenuhnya memenuhi persyaratan jenis koleksi (misalnya, metode Add hilang), jenisnya tidak dianggap sebagai jenis koleksi, dan dengan demikian atribut SerializableAttribute dan antarmuka ISerializable digunakan untuk menentukan apakah jenis tersebut dapat diserialisasikan.

  • Menerapkan atribut CollectionDataContractAttribute ke koleksi untuk menyesuaikannya akan menghapus mekanisme fallback SerializableAttribute sebelumnya. Sebaliknya, jika koleksi yang disesuaikan tidak memenuhi persyaratan jenis koleksi, pengecualian InvalidDataContractException akan dibuat. String pengecualian sering berisi informasi yang menjelaskan alasan jenis tertentu tidak dianggap sebagai koleksi yang valid (tanpa metode Add, tidak ada konstruktor tanpa parameter, dan sebagainya), sehingga sering kali berguna untuk menerapkan atribut CollectionDataContractAttribute untuk tujuan penelusuran kesalahan.

Penamaan Koleksi

Berikut ini adalah daftar aturan penamaan koleksi:

  • Namespace default untuk semua kontrak data koleksi kamus, serta untuk kontrak data koleksi daftar yang berisi jenis primitif, kecuali http://schemas.microsoft.com/2003/10/Serialization/Arrays ditimpa menggunakan Namespace. Jenis yang memetakan ke jenis XSD bawaan, serta jenis char, Timespan, dan Guid, dianggap primitif untuk tujuan ini.

  • Namespace layanan default untuk jenis koleksi yang berisi jenis non-primitif, kecuali jika ditimpa menggunakan Namespace, sama dengan namespace kontrak data dari jenis yang terkandung dalam koleksi.

  • Nama default untuk kontrak data koleksi daftar, kecuali ditimpa menggunakan Nama, adalah string "ArrayOf" yang dikombinasikan dengan nama kontrak data dari jenis yang terkandung dalam koleksi. Misalnya, nama kontrak data untuk Daftar Bilangan Bulat Generik adalah "ArrayOfint". Perlu diingat bahwa nama kontrak data Object adalah "anyType", sehingga nama kontrak data dari daftar non-generik seperti ArrayList adalah "ArrayOfanyType".

Nama default untuk kontrak data koleksi kamus, kecuali ditimpa menggunakan Name, adalah string "ArrayOfKeyValueOf" yang dikombinasikan dengan nama kontrak data jenis kunci diikuti dengan nama kontrak data dari jenis nilai. Misalnya, nama kontrak data untuk Kamus Generik String dan Bilangan Bulat adalah "ArrayOfKeyValueOfstringint". Selain itu, jika kunci atau jenis nilai bukan jenis primitif, hash namespace dari namespace kontrak data jenis kunci dan nilai ditambahkan ke nama. Untuk mengetahui informasi selengkapnya tentang hash namespace, lihat Nama Kontrak Data.

Setiap kontrak data pengumpulan kamus memiliki kontrak data pendamping yang mewakili satu entri dalam kamus. Namanya sama dengan untuk kontrak data kamus, kecuali untuk awalan "ArrayOf", dan namespace-nya sama dengan untuk kontrak data kamus. Misalnya, untuk kontrak data kamus "ArrayOfKeyValueOfstringint", kontrak data "KeyValueofstringint" mewakili satu entri dalam kamus. Anda dapat menyesuaikan nama kontrak data ini dengan menggunakan properti ItemName, seperti yang dijelaskan di bagian berikutnya.

Aturan penamaan jenis generik, seperti yang dijelaskan dalam Nama Kontrak Data, sepenuhnya berlaku untuk jenis koleksi; artinya, Anda dapat menggunakan kurung kurawal dalam Nama untuk menunjukkan parameter jenis generik. Namun, angka dalam kurung kurawal mengacu pada parameter generik dan bukan jenis yang terkandung dalam koleksi.

Kustomisasi Koleksi

Penggunaan atribut CollectionDataContractAttribute berikut dilarang dan menghasilkan pengecualian InvalidDataContractException:

Aturan Polimorfisme

Seperti yang disebutkan sebelumnya, menyesuaikan koleksi dengan menggunakan atribut CollectionDataContractAttribute dapat mengganggu pertukaran koleksi. Dua jenis koleksi yang disesuaikan hanya dapat dianggap setara jika nama, namespace, nama item, serta nama kunci dan nilai (jika ini adalah koleksi kamus) yang cocok.

Karena penyesuaian, dimungkinkan untuk secara tidak sengaja menggunakan satu kontrak data koleksi saat yang lain diharapkan. Hal ini harus dihindari. Lihat jenis berikut.

[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

Dalam hal ini, instans Marks1 dapat ditetapkan ke testMarks. Namun, Marks2 tidak boleh digunakan karena kontrak datanya tidak dianggap setara dengan kontrak data IList<int>. Nama kontrak data adalah "Marks2" dan bukan "ArrayOfint", dan nama elemen berulang adalah "<mark>" dan bukan "<int>".

Aturan dalam tabel berikut berlaku untuk penugasan polimorfik koleksi.

Jenis yang dinyatakan Menetapkan koleksi yang tidak disesuaikan Menetapkan koleksi yang disesuaikan
Objek Nama kontrak diserialisasikan. Nama kontrak diserialisasikan.

Penyesuaian digunakan.
Antarmuka koleksi Nama kontrak tidak diserialisasikan. Nama kontrak tidak diserialisasikan.

Kustomisasi tidak digunakan.*
Koleksi yang tidak disesuaikan Nama kontrak tidak diserialisasikan. Nama kontrak diserialisasikan.

Penyesuaian digunakan.**
Koleksi yang disesuaikan Nama kontrak diserialisasikan. Penyesuaian tidak digunakan.** Nama kontrak diserialisasikan.

Penyesuaian jenis yang ditetapkan digunakan.**

*Dengan kelas NetDataContractSerializer, penyesuaian digunakan dalam kasus ini. Kelas NetDataContractSerializer juga menserialisasikan nama jenis aktual dalam kasus ini, sehingga deserialisasi berfungsi seperti yang diharapkan.

**Kasus ini mengakibatkan instans yang tidak valid terhadap skema dan dengan demikian harus dihindari.

Dalam kasus saat nama kontrak diserialisasikan, jenis koleksi yang ditetapkan harus berada dalam daftar jenis yang diketahui. Sebaliknya juga benar: dalam kasus saat nama tidak diserialisasikan, menambahkan jenis ke daftar jenis yang diketahui tidak diperlukan.

Array dari jenis turunan dapat ditetapkan ke array dari jenis dasar. Dalam hal ini, nama kontrak untuk jenis turunan diserialisasikan untuk setiap elemen berulang. Misalnya, jika jenis Book berasal dari jenis LibraryItem, Anda dapat menetapkan array Book ke array LibraryItem. Ini tidak berlaku untuk jenis koleksi lainnya. Misalnya, Anda tidak dapat menetapkan Generic List of Book ke Generic List of LibraryItem. Namun, Anda dapat menetapkan Generic List of LibraryItem yang berisi instans Book. Dalam array dan kasus non-array, Book harus berada dalam daftar jenis yang diketahui.

Preservasi Referensi Koleksi dan Objek

Saat serializer berfungsi dalam mode saat serializer mempertahankan referensi objek, mempertahankan referensi objek juga berlaku untuk koleksi. Secara khusus, identitas objek dipertahankan untuk seluruh koleksi dan item individual yang terkandung dalam koleksi. Untuk kamus, identitas objek dipertahankan baik untuk objek pasangan kunci/nilai maupun objek kunci dan nilai individual.

Lihat juga