次の方法で共有


KeyedCollection<TKey,TItem>.InsertItem(Int32, TItem) メソッド

定義

KeyedCollection<TKey,TItem> 内の指定したインデックスの位置に要素を挿入します。

protected:
 override void InsertItem(int index, TItem item);
protected override void InsertItem (int index, TItem item);
override this.InsertItem : int * 'Item -> unit
Protected Overrides Sub InsertItem (index As Integer, item As TItem)

パラメーター

index
Int32

item を挿入する位置の、0 から始まるインデックス。

item
TItem

挿入するオブジェクト。

例外

index が 0 未満です。

または

indexCount より大きくなっています。

このセクションには、コレクションにオブジェクトを追加または挿入するためのカスタム動作を提供するために メソッドを InsertItem オーバーライドする方法を示す 2 つのコード例が含まれています。 最初の例ではカスタム通知イベントを追加し、2 番目の例では変更可能なキーを持つオブジェクトのコレクションをサポートしています。

例 1

次のコード例は、保護された InsertItem、、ClearItemsRemoveItem、および メソッドをオーバーライドして、および SetItem メソッドのカスタム動作AddRemoveを提供しClear、既定Item[]のプロパティ (C# のインデクサー) を設定する方法を示しています。 この例で提供されるカスタム動作は、 という名前 Changedの通知イベントです。これは、オーバーライドされた各メソッドの最後に発生します。

このコード例では、 から派生KeyedCollection<TKey,TItem>し、単純な注文フォームを表す クラスを作成SimpleOrderします。 注文フォームには、順序付けされた OrderItem アイテムを表すオブジェクトが含まれています。 また、このコード例では、イベント情報を SimpleOrderChangedEventArgs 格納するクラスと、変更の種類を識別する列挙も作成します。

このコード例では、 クラスの メソッドで派生クラスのプロパティとメソッドを呼び出すことで、 Main カスタム動作を Demo 示します。

このコード例では、変更できないキーを持つオブジェクトを使用します。 変更可能なキーを使用するコード例については、「」を参照してください ChangeItemKey

using namespace System;
using namespace System::Collections::Generic;
using namespace System::Collections::ObjectModel;

public enum class ChangeTypes
{
    Added,
    Removed, 
    Replaced, 
    Cleared
};

ref class SimpleOrderChangedEventArgs; 

// This class represents a simple line item in an order. All the 
// values are immutable except quantity.
// 
public ref class OrderItem
{
private:
    int _quantity;

public:
    initonly int PartNumber;
    initonly String^ Description;
    initonly double UnitPrice;
        
    OrderItem(int partNumber, String^ description, int quantity, 
        double unitPrice)
    {
        this->PartNumber = partNumber;
        this->Description = description;
        this->Quantity = quantity;
        this->UnitPrice = unitPrice;
    };
    
    property int Quantity    
    {
        int get() { return _quantity; };
        void set(int value)
        {
            if (value < 0)
                throw gcnew ArgumentException("Quantity cannot be negative.");
            
            _quantity = value;
        };
    };
        
    virtual String^ ToString() override 
    {
        return String::Format(
            "{0,9} {1,6} {2,-12} at {3,8:#,###.00} = {4,10:###,###.00}", 
            PartNumber, _quantity, Description, UnitPrice, 
            UnitPrice * _quantity);
    };
};

// Event argument for the Changed event.
//
public ref class SimpleOrderChangedEventArgs : EventArgs
{
public:
    OrderItem^ ChangedItem;
    initonly ChangeTypes ChangeType;
    OrderItem^ ReplacedWith;

    SimpleOrderChangedEventArgs(ChangeTypes change, 
        OrderItem^ item, OrderItem^ replacement)
    {
        this->ChangeType = change;
        this->ChangedItem = item;
        this->ReplacedWith = replacement;
    }
};

// This class derives from KeyedCollection and shows how to override
// the protected ClearItems, InsertItem, RemoveItem, and SetItem 
// methods in order to change the behavior of the default Item 
// property and the Add, Clear, Insert, and Remove methods. The
// class implements a Changed event, which is raised by all the
// protected methods.
//
// SimpleOrder is a collection of OrderItem objects, and its key
// is the PartNumber field of OrderItem-> PartNumber is an Integer,
// so SimpleOrder inherits KeyedCollection<int, OrderItem>.
// (Note that the key of OrderItem cannot be changed; if it could 
// be changed, SimpleOrder would have to override ChangeItemKey.)
//
public ref class SimpleOrder : KeyedCollection<int, OrderItem^>
{
public:
    event EventHandler<SimpleOrderChangedEventArgs^>^ Changed;

    // This parameterless constructor calls the base class constructor
    // that specifies a dictionary threshold of 0, so that the internal
    // dictionary is created as soon as an item is added to the 
    // collection.
    //
    SimpleOrder() : KeyedCollection<int, OrderItem^>(nullptr, 0) {};
    
    // This is the only method that absolutely must be overridden,
    // because without it the KeyedCollection cannot extract the
    // keys from the items. 
    //
protected:
    virtual int GetKeyForItem(OrderItem^ item) override
    {
        // In this example, the key is the part number.
        return item->PartNumber;
    }

    virtual void InsertItem(int index, OrderItem^ newItem) override 
    {
        __super::InsertItem(index, newItem);

        Changed(this, gcnew SimpleOrderChangedEventArgs(
            ChangeTypes::Added, newItem, nullptr));
    }

    virtual void SetItem(int index, OrderItem^ newItem) override 
    {
        OrderItem^ replaced = this->Items[index];
        __super::SetItem(index, newItem);

        Changed(this, gcnew SimpleOrderChangedEventArgs(
            ChangeTypes::Replaced, replaced, newItem));
    }

    virtual void RemoveItem(int index) override 
    {
        OrderItem^ removedItem = Items[index];
        __super::RemoveItem(index);

        Changed(this, gcnew SimpleOrderChangedEventArgs(
            ChangeTypes::Removed, removedItem, nullptr));
    }

    virtual void ClearItems() override 
    {
        __super::ClearItems();

        Changed(this, gcnew SimpleOrderChangedEventArgs(
            ChangeTypes::Cleared, nullptr, nullptr));
    }

    // This method uses the internal reference to the dictionary
    // to test fo
public:
    void AddOrMerge(OrderItem^ newItem)
    {

        int key = this->GetKeyForItem(newItem);
        OrderItem^ existingItem = nullptr;

        // The dictionary is not created until the first item is 
        // added, so it is necessary to test for null. Using 
        // AndAlso ensures that TryGetValue is not called if the
        // dictionary does not exist.
        //
        if (this->Dictionary != nullptr && 
            this->Dictionary->TryGetValue(key, existingItem))
        {
            existingItem->Quantity += newItem->Quantity;
        }
        else
        {
            this->Add(newItem);
        }
    }
};

public ref class Demo
{    
public:
    static void Main()
    {
        SimpleOrder^ weekly = gcnew SimpleOrder();
        weekly->Changed += gcnew 
            EventHandler<SimpleOrderChangedEventArgs^>(ChangedHandler);

        // The Add method, inherited from Collection, takes OrderItem->
        //
        weekly->Add(gcnew OrderItem(110072674, "Widget", 400, 45.17));
        weekly->Add(gcnew OrderItem(110072675, "Sprocket", 27, 5.3));
        weekly->Add(gcnew OrderItem(101030411, "Motor", 10, 237.5));
        weekly->Add(gcnew OrderItem(110072684, "Gear", 175, 5.17));

        Display(weekly);
        
        // The Contains method of KeyedCollection takes TKey.
        //
        Console::WriteLine("\nContains(101030411): {0}", 
            weekly->Contains(101030411));

        // The default Item property of KeyedCollection takes the key
        // type, Integer. The property is read-only.
        //
        Console::WriteLine("\nweekly[101030411]->Description: {0}", 
            weekly[101030411]->Description);

        // The Remove method of KeyedCollection takes a key.
        //
        Console::WriteLine("\nRemove(101030411)");
        weekly->Remove(101030411);

        // The Insert method, inherited from Collection, takes an 
        // index and an OrderItem.
        //
        Console::WriteLine("\nInsert(2, gcnew OrderItem(...))");
        weekly->Insert(2, gcnew OrderItem(111033401, "Nut", 10, .5));
         
        // The default Item property is overloaded. One overload comes
        // from KeyedCollection<int, OrderItem>; that overload
        // is read-only, and takes Integer because it retrieves by key. 
        // The other overload comes from Collection<OrderItem>, the 
        // base class of KeyedCollection<int, OrderItem>; it 
        // retrieves by index, so it also takes an Integer. The compiler
        // uses the most-derived overload, from KeyedCollection, so the
        // only way to access SimpleOrder by index is to cast it to
        // Collection<OrderItem>. Otherwise the index is interpreted
        // as a key, and KeyNotFoundException is thrown.
        //
        Collection<OrderItem^>^ coweekly = weekly;
        Console::WriteLine("\ncoweekly[2].Description: {0}", 
            coweekly[2]->Description);
 
        Console::WriteLine("\ncoweekly[2] = gcnew OrderItem(...)");
        coweekly[2] = gcnew OrderItem(127700026, "Crank", 27, 5.98);

        OrderItem^ temp = coweekly[2];

        // The IndexOf method, inherited from Collection<OrderItem>, 
        // takes an OrderItem instead of a key.
        // 
        Console::WriteLine("\nIndexOf(temp): {0}", weekly->IndexOf(temp));

        // The inherited Remove method also takes an OrderItem->
        //
        Console::WriteLine("\nRemove(temp)");
        weekly->Remove(temp);

        Console::WriteLine("\nRemoveAt(0)");
        weekly->RemoveAt(0);

        weekly->AddOrMerge(gcnew OrderItem(110072684, "Gear", 1000, 5.17));

        Display(weekly);

        Console::WriteLine();
        weekly->Clear();
    }
    
private:
    static void Display(SimpleOrder^ order)
    {
        Console::WriteLine();
        for each( OrderItem^ item in order )
        {
            Console::WriteLine(item);
        }
    }

    static void ChangedHandler(Object^ source, 
        SimpleOrderChangedEventArgs^ e)
    {
        OrderItem^ item = e->ChangedItem;

        if (e->ChangeType == ChangeTypes::Replaced)
        {
            OrderItem^ replacement = e->ReplacedWith;

            Console::WriteLine("{0} (quantity {1}) was replaced " +
                "by {2}, (quantity {3}).", item->Description, 
                item->Quantity, replacement->Description, 
                replacement->Quantity);
        }
        else if(e->ChangeType == ChangeTypes::Cleared)
        {
            Console::WriteLine("The order list was cleared.");
        }
        else
        {
            Console::WriteLine("{0} (quantity {1}) was {2}.", 
                item->Description, item->Quantity, e->ChangeType);
        }
    }
};

void main()
{
    Demo::Main();
}

/* This code example produces the following output:

Widget (quantity 400) was Added.
Sprocket (quantity 27) was Added.
Motor (quantity 10) was Added.
Gear (quantity 175) was Added.

110072674    400 Widget       at    45.17 =  18,068.00
110072675     27 Sprocket     at     5.30 =     143.10
101030411     10 Motor        at   237.50 =   2,375.00
110072684    175 Gear         at     5.17 =     904.75

Contains(101030411): True

weekly[101030411]->Description: Motor

Remove(101030411)
Motor (quantity 10) was Removed.

Insert(2, gcnew OrderItem(...))
Nut (quantity 10) was Added.

coweekly[2].Description: Nut

coweekly[2] = gcnew OrderItem(...)
Nut (quantity 10) was replaced by Crank, (quantity 27).

IndexOf(temp): 2

Remove(temp)
Crank (quantity 27) was Removed.

RemoveAt(0)
Widget (quantity 400) was Removed.

110072675     27 Sprocket     at     5.30 =     143.10
110072684   1175 Gear         at     5.17 =   6,074.75

The order list was cleared.
 */
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;

// This class derives from KeyedCollection and shows how to override
// the protected ClearItems, InsertItem, RemoveItem, and SetItem
// methods in order to change the behavior of the default Item
// property and the Add, Clear, Insert, and Remove methods. The
// class implements a Changed event, which is raised by all the
// protected methods.
//
// SimpleOrder is a collection of OrderItem objects, and its key
// is the PartNumber field of OrderItem. PartNumber is an Integer,
// so SimpleOrder inherits KeyedCollection<int, OrderItem>.
// (Note that the key of OrderItem cannot be changed; if it could
// be changed, SimpleOrder would have to override ChangeItemKey.)
//
public class SimpleOrder : KeyedCollection<int, OrderItem>
{
    public event EventHandler<SimpleOrderChangedEventArgs> Changed;

    // This parameterless constructor calls the base class constructor
    // that specifies a dictionary threshold of 0, so that the internal
    // dictionary is created as soon as an item is added to the
    // collection.
    //
    public SimpleOrder() : base(null, 0) {}

    // This is the only method that absolutely must be overridden,
    // because without it the KeyedCollection cannot extract the
    // keys from the items.
    //
    protected override int GetKeyForItem(OrderItem item)
    {
        // In this example, the key is the part number.
        return item.PartNumber;
    }

    protected override void InsertItem(int index, OrderItem newItem)
    {
        base.InsertItem(index, newItem);

        EventHandler<SimpleOrderChangedEventArgs> temp = Changed;
        if (temp != null)
        {
            temp(this, new SimpleOrderChangedEventArgs(
                ChangeType.Added, newItem, null));
        }
    }

    protected override void SetItem(int index, OrderItem newItem)
    {
        OrderItem replaced = Items[index];
        base.SetItem(index, newItem);

        EventHandler<SimpleOrderChangedEventArgs> temp = Changed;
        if (temp != null)
        {
            temp(this, new SimpleOrderChangedEventArgs(
                ChangeType.Replaced, replaced, newItem));
        }
    }

    protected override void RemoveItem(int index)
    {
        OrderItem removedItem = Items[index];
        base.RemoveItem(index);

        EventHandler<SimpleOrderChangedEventArgs> temp = Changed;
        if (temp != null)
        {
            temp(this, new SimpleOrderChangedEventArgs(
                ChangeType.Removed, removedItem, null));
        }
    }

    protected override void ClearItems()
    {
        base.ClearItems();

        EventHandler<SimpleOrderChangedEventArgs> temp = Changed;
        if (temp != null)
        {
            temp(this, new SimpleOrderChangedEventArgs(
                ChangeType.Cleared, null, null));
        }
    }
}

// Event argument for the Changed event.
//
public class SimpleOrderChangedEventArgs : EventArgs
{
    private OrderItem _changedItem;
    private ChangeType _changeType;
    private OrderItem _replacedWith;

    public OrderItem ChangedItem { get { return _changedItem; }}
    public ChangeType ChangeType { get { return _changeType; }}
    public OrderItem ReplacedWith { get { return _replacedWith; }}

    public SimpleOrderChangedEventArgs(ChangeType change,
        OrderItem item, OrderItem replacement)
    {
        _changeType = change;
        _changedItem = item;
        _replacedWith = replacement;
    }
}

public enum ChangeType
{
    Added,
    Removed,
    Replaced,
    Cleared
};

public class Demo
{
    public static void Main()
    {
        SimpleOrder weekly = new SimpleOrder();
        weekly.Changed += new
            EventHandler<SimpleOrderChangedEventArgs>(ChangedHandler);

        // The Add method, inherited from Collection, takes OrderItem.
        //
        weekly.Add(new OrderItem(110072674, "Widget", 400, 45.17));
        weekly.Add(new OrderItem(110072675, "Sprocket", 27, 5.3));
        weekly.Add(new OrderItem(101030411, "Motor", 10, 237.5));
        weekly.Add(new OrderItem(110072684, "Gear", 175, 5.17));

        Display(weekly);

        // The Contains method of KeyedCollection takes TKey.
        //
        Console.WriteLine("\nContains(101030411): {0}",
            weekly.Contains(101030411));

        // The default Item property of KeyedCollection takes the key
        // type, Integer. The property is read-only.
        //
        Console.WriteLine("\nweekly[101030411].Description: {0}",
            weekly[101030411].Description);

        // The Remove method of KeyedCollection takes a key.
        //
        Console.WriteLine("\nRemove(101030411)");
        weekly.Remove(101030411);

        // The Insert method, inherited from Collection, takes an
        // index and an OrderItem.
        //
        Console.WriteLine("\nInsert(2, new OrderItem(...))");
        weekly.Insert(2, new OrderItem(111033401, "Nut", 10, .5));

        // The default Item property is overloaded. One overload comes
        // from KeyedCollection<int, OrderItem>; that overload
        // is read-only, and takes Integer because it retrieves by key.
        // The other overload comes from Collection<OrderItem>, the
        // base class of KeyedCollection<int, OrderItem>; it
        // retrieves by index, so it also takes an Integer. The compiler
        // uses the most-derived overload, from KeyedCollection, so the
        // only way to access SimpleOrder by index is to cast it to
        // Collection<OrderItem>. Otherwise the index is interpreted
        // as a key, and KeyNotFoundException is thrown.
        //
        Collection<OrderItem> coweekly = weekly;
        Console.WriteLine("\ncoweekly[2].Description: {0}",
            coweekly[2].Description);

        Console.WriteLine("\ncoweekly[2] = new OrderItem(...)");
        coweekly[2] = new OrderItem(127700026, "Crank", 27, 5.98);

        OrderItem temp = coweekly[2];

        // The IndexOf method, inherited from Collection<OrderItem>,
        // takes an OrderItem instead of a key.
        //
        Console.WriteLine("\nIndexOf(temp): {0}", weekly.IndexOf(temp));

        // The inherited Remove method also takes an OrderItem.
        //
        Console.WriteLine("\nRemove(temp)");
        weekly.Remove(temp);

        Console.WriteLine("\nRemoveAt(0)");
        weekly.RemoveAt(0);

        // Increase the quantity for a line item.
        Console.WriteLine("\ncoweekly(1) = New OrderItem(...)");
        coweekly[1] = new OrderItem(coweekly[1].PartNumber,
            coweekly[1].Description, coweekly[1].Quantity + 1000,
            coweekly[1].UnitPrice);

        Display(weekly);

        Console.WriteLine();
        weekly.Clear();
    }

    private static void Display(SimpleOrder order)
    {
        Console.WriteLine();
        foreach( OrderItem item in order )
        {
            Console.WriteLine(item);
        }
    }

    private static void ChangedHandler(object source,
        SimpleOrderChangedEventArgs e)
    {

        OrderItem item = e.ChangedItem;

        if (e.ChangeType==ChangeType.Replaced)
        {
            OrderItem replacement = e.ReplacedWith;

            Console.WriteLine("{0} (quantity {1}) was replaced " +
                "by {2}, (quantity {3}).", item.Description,
                item.Quantity, replacement.Description,
                replacement.Quantity);
        }
        else if(e.ChangeType == ChangeType.Cleared)
        {
            Console.WriteLine("The order list was cleared.");
        }
        else
        {
            Console.WriteLine("{0} (quantity {1}) was {2}.",
                item.Description, item.Quantity, e.ChangeType);
        }
    }
}

// This class represents a simple line item in an order. All the
// values are immutable except quantity.
//
public class OrderItem
{
    private int _partNumber;
    private string _description;
    private double _unitPrice;
    private int _quantity;

    public int PartNumber { get { return _partNumber; }}
    public string Description { get { return _description; }}
    public double UnitPrice { get { return _unitPrice; }}
    public int Quantity { get { return _quantity; }}

    public OrderItem(int partNumber, string description, int quantity,
        double unitPrice)
    {
        _partNumber = partNumber;
        _description = description;
        _quantity = quantity;
        _unitPrice = unitPrice;
    }

    public override string ToString()
    {
        return String.Format(
            "{0,9} {1,6} {2,-12} at {3,8:#,###.00} = {4,10:###,###.00}",
            PartNumber, _quantity, Description, UnitPrice,
            UnitPrice * _quantity);
    }
}

/* This code example produces the following output:

Widget (quantity 400) was Added.
Sprocket (quantity 27) was Added.
Motor (quantity 10) was Added.
Gear (quantity 175) was Added.

110072674    400 Widget       at    45.17 =  18,068.00
110072675     27 Sprocket     at     5.30 =     143.10
101030411     10 Motor        at   237.50 =   2,375.00
110072684    175 Gear         at     5.17 =     904.75

Contains(101030411): True

weekly[101030411].Description: Motor

Remove(101030411)
Motor (quantity 10) was Removed.

Insert(2, new OrderItem(...))
Nut (quantity 10) was Added.

coweekly[2].Description: Nut

coweekly[2] = new OrderItem(...)
Nut (quantity 10) was replaced by Crank, (quantity 27).

IndexOf(temp): 2

Remove(temp)
Crank (quantity 27) was Removed.

RemoveAt(0)
Widget (quantity 400) was Removed.

coweekly(1) = New OrderItem(...)
Gear (quantity 175) was replaced by Gear, (quantity 1175).

110072675     27 Sprocket     at     5.30 =     143.10
110072684   1175 Gear         at     5.17 =   6,074.75

The order list was cleared.
 */
Imports System.Collections.Generic
Imports System.Collections.ObjectModel

' This class derives from KeyedCollection and shows how to override
' the protected ClearItems, InsertItem, RemoveItem, and SetItem 
' methods in order to change the behavior of the default Item 
' property and the Add, Clear, Insert, and Remove methods. The
' class implements a Changed event, which is raised by all the
' protected methods.
'
' SimpleOrder is a collection of OrderItem objects, and its key
' is the PartNumber field of OrderItem. PartNumber is an Integer,
' so SimpleOrder inherits KeyedCollection(Of Integer, OrderItem).
' (Note that the key of OrderItem cannot be changed; if it could 
' be changed, SimpleOrder would have to override ChangeItemKey.)
'
Public Class SimpleOrder
    Inherits KeyedCollection(Of Integer, OrderItem)

    Public Event Changed As EventHandler(Of SimpleOrderChangedEventArgs)

    ' This parameterless constructor calls the base class constructor
    ' that specifies a dictionary threshold of 0, so that the internal
    ' dictionary is created as soon as an item is added to the 
    ' collection.
    '
    Public Sub New()
        MyBase.New(Nothing, 0)
    End Sub
    
    ' This is the only method that absolutely must be overridden,
    ' because without it the KeyedCollection cannot extract the
    ' keys from the items. 
    '
    Protected Overrides Function GetKeyForItem( _
        ByVal item As OrderItem) As Integer

        ' In this example, the key is the part number.
        Return item.PartNumber   
    End Function

    Protected Overrides Sub InsertItem( _
        ByVal index As Integer, ByVal newItem As OrderItem)

        MyBase.InsertItem(index, newItem)

        RaiseEvent Changed(Me, New SimpleOrderChangedEventArgs( _
            ChangeType.Added, newItem, Nothing))
    End Sub

    Protected Overrides Sub SetItem(ByVal index As Integer, _
        ByVal newItem As OrderItem)

        Dim replaced As OrderItem = Items(index)
        MyBase.SetItem(index, newItem)

        RaiseEvent Changed(Me, New SimpleOrderChangedEventArgs( _
            ChangeType.Replaced, replaced, newItem))
    End Sub

    Protected Overrides Sub RemoveItem(ByVal index As Integer)

        Dim removedItem As OrderItem = Items(index)
        MyBase.RemoveItem(index)

        RaiseEvent Changed(Me, New SimpleOrderChangedEventArgs( _
            ChangeType.Removed, removedItem, Nothing))
    End Sub

    Protected Overrides Sub ClearItems()
        MyBase.ClearItems()

        RaiseEvent Changed(Me, New SimpleOrderChangedEventArgs( _
            ChangeType.Cleared, Nothing, Nothing))
    End Sub

End Class

' Event argument for the Changed event.
'
Public Class SimpleOrderChangedEventArgs
    Inherits EventArgs

    Private _changedItem As OrderItem
    Private _changeType As ChangeType
    Private _replacedWith As OrderItem

    Public ReadOnly Property ChangedItem As OrderItem
        Get
            Return _changedItem
        End Get
    End Property

    Public ReadOnly Property ChangeType As ChangeType
        Get
            Return _changeType
        End Get
    End Property

    Public ReadOnly Property ReplacedWith As OrderItem
        Get
            Return _replacedWith
        End Get
    End Property

    Public Sub New(ByVal change As ChangeType, ByVal item As OrderItem, _
        ByVal replacement As OrderItem)

        _changeType = change
        _changedItem = item
        _replacedWith = replacement
    End Sub
End Class

Public Enum ChangeType
    Added
    Removed
    Replaced
    Cleared
End Enum

Public Class Demo
    
    Public Shared Sub Main() 
        Dim weekly As New SimpleOrder()
        AddHandler weekly.Changed, AddressOf ChangedHandler

        ' The Add method, inherited from Collection, takes OrderItem.
        '
        weekly.Add(New OrderItem(110072674, "Widget", 400, 45.17))
        weekly.Add(New OrderItem(110072675, "Sprocket", 27, 5.3))
        weekly.Add(New OrderItem(101030411, "Motor", 10, 237.5))
        weekly.Add(New OrderItem(110072684, "Gear", 175, 5.17))

        Display(weekly)
        
        ' The Contains method of KeyedCollection takes TKey.
        '
        Console.WriteLine(vbLf & "Contains(101030411): {0}", _
            weekly.Contains(101030411))

        ' The default Item property of KeyedCollection takes the key
        ' type, Integer. The property is read-only.
        '
        Console.WriteLine(vbLf & "weekly(101030411).Description: {0}", _
            weekly(101030411).Description)

        ' The Remove method of KeyedCollection takes a key.
        '
        Console.WriteLine(vbLf & "Remove(101030411)")
        weekly.Remove(101030411)

        ' The Insert method, inherited from Collection, takes an 
        ' index and an OrderItem.
        '
        Console.WriteLine(vbLf & "Insert(2, New OrderItem(...))")
        weekly.Insert(2, New OrderItem(111033401, "Nut", 10, .5))
         
        ' The default Item property is overloaded. One overload comes
        ' from KeyedCollection(Of Integer, OrderItem); that overload
        ' is read-only, and takes Integer because it retrieves by key. 
        ' The other overload comes from Collection(Of OrderItem), the 
        ' base class of KeyedCollection(Of Integer, OrderItem); it 
        ' retrieves by index, so it also takes an Integer. The compiler
        ' uses the most-derived overload, from KeyedCollection, so the
        ' only way to access SimpleOrder by index is to cast it to
        ' Collection(Of OrderItem). Otherwise the index is interpreted
        ' as a key, and KeyNotFoundException is thrown.
        '
        Dim coweekly As Collection(Of OrderItem) = weekly
        Console.WriteLine(vbLf & "coweekly(2).Description: {0}", _
            coweekly(2).Description)
 
        Console.WriteLine(vbLf & "coweekly(2) = New OrderItem(...)")
        coweekly(2) = New OrderItem(127700026, "Crank", 27, 5.98)

        Dim temp As OrderItem = coweekly(2)

        ' The IndexOf method, inherited from Collection(Of OrderItem), 
        ' takes an OrderItem instead of a key.
        ' 
        Console.WriteLine(vbLf & "IndexOf(temp): {0}", _
            weekly.IndexOf(temp))

        ' The inherited Remove method also takes an OrderItem.
        '
        Console.WriteLine(vbLf & "Remove(temp)")
        weekly.Remove(temp)

        Console.WriteLine(vbLf & "RemoveAt(0)")
        weekly.RemoveAt(0)

        ' Increase the quantity for a line item.
        Console.WriteLine(vbLf & "coweekly(1) = New OrderItem(...)")
        coweekly(1) = New OrderItem(coweekly(1).PartNumber, _
            coweekly(1).Description, coweekly(1).Quantity + 1000, _
            coweekly(1).UnitPrice)

        Display(weekly)

        Console.WriteLine()
        weekly.Clear()
    End Sub
    
    Private Shared Sub Display(ByVal order As SimpleOrder) 
        Console.WriteLine()
        For Each item As OrderItem In  order
            Console.WriteLine(item)
        Next item
    End Sub

    Private Shared Sub ChangedHandler(ByVal source As Object, _
        ByVal e As SimpleOrderChangedEventArgs)

        Dim item As OrderItem = e.ChangedItem

        If e.ChangeType = ChangeType.Replaced Then
            Dim replacement As OrderItem = e.ReplacedWith

            Console.WriteLine("{0} (quantity {1}) was replaced " & _
                "by {2}, (quantity {3}).", item.Description, _
                item.Quantity, replacement.Description, replacement.Quantity)

        ElseIf e.ChangeType = ChangeType.Cleared Then
            Console.WriteLine("The order list was cleared.")

        Else
            Console.WriteLine("{0} (quantity {1}) was {2}.", _
                item.Description, item.Quantity, e.ChangeType)
        End If
    End Sub
End Class

' This class represents a simple line item in an order. All the 
' values are immutable except quantity.
' 
Public Class OrderItem
    
    Private _partNumber As Integer
    Private _description As String
    Private _unitPrice As Double
    Private _quantity As Integer

    Public ReadOnly Property PartNumber As Integer
        Get
            Return _partNumber
        End Get
    End Property

    Public ReadOnly Property Description As String
        Get
            Return _description
        End Get
    End Property

    Public ReadOnly Property UnitPrice As Double
        Get
            Return _unitPrice
        End Get
    End Property
    
    Public ReadOnly Property Quantity() As Integer 
        Get
            Return _quantity
        End Get
    End Property
    
    Public Sub New(ByVal partNumber As Integer, _
                   ByVal description As String, _
                   ByVal quantity As Integer, _
                   ByVal unitPrice As Double) 
        _partNumber = partNumber
        _description = description
        _quantity = quantity
        _unitPrice = unitPrice
    End Sub
        
    Public Overrides Function ToString() As String 
        Return String.Format( _
            "{0,9} {1,6} {2,-12} at {3,8:#,###.00} = {4,10:###,###.00}", _
            PartNumber, _quantity, Description, UnitPrice, _
            UnitPrice * _quantity)
    End Function
End Class

' This code example produces the following output:
'
'Widget (quantity 400) was Added.
'Sprocket (quantity 27) was Added.
'Motor (quantity 10) was Added.
'Gear (quantity 175) was Added.
'
'110072674    400 Widget       at    45.17 =  18,068.00
'110072675     27 Sprocket     at     5.30 =     143.10
'101030411     10 Motor        at   237.50 =   2,375.00
'110072684    175 Gear         at     5.17 =     904.75
'
'Contains(101030411): True
'
'weekly(101030411).Description: Motor
'
'Remove(101030411)
'Motor (quantity 10) was Removed.
'
'Insert(2, New OrderItem(...))
'Nut (quantity 10) was Added.
'
'coweekly(2).Description: Nut
'
'coweekly(2) = New OrderItem(...)
'Nut (quantity 10) was replaced by Crank, (quantity 27).
'
'IndexOf(temp): 2
'
'Remove(temp)
'Crank (quantity 27) was Removed.
'
'RemoveAt(0)
'Widget (quantity 400) was Removed.
'
'coweekly(1) = New OrderItem(...)
'Gear (quantity 175) was replaced by Gear, (quantity 1175).
'
'110072675     27 Sprocket     at     5.30 =     143.10
'110072684   1175 Gear         at     5.17 =   6,074.75
'
'The order list was cleared.

例 2

次のコード例は、変更可能なキーをサポートするように保護された ChangeItemKey メソッドをオーバーライドする方法と、キーとコレクションの整合性を維持するために保護された InsertItemRemoveItemClearItems、および SetItem メソッドをオーバーライドする方法を示しています。

コード例では、 から派生KeyedCollection<TKey,TItem>する コレクションと クラスをMutableKey作成MutableKeysします。 クラスには MutableKey settable プロパティがあります Key 。 プロパティに新しいキーが割り当てられると、プロパティ セッターはコレクションの internal (Friend Visual Basic では) ChangeKey メソッドを呼び出して、新しいキーが既存のキーと競合するかどうかをテストします。 その場合、例外がスローされ、プロパティ値は変更されません。

オブジェクトとMutableKeysコレクションの間の接続をMutableKey維持し、オブジェクトが 2 つのコレクションに挿入されないようにするために、 MutableKey クラスには internal (Friend Visual Basic の場合) Collection フィールドがあります。 このフィールドは、コレクションに項目を追加したりコレクションから削除したりするためのカスタム動作を提供する、保護されたメソッド (メソッドなど InsertItem ) によって管理されます。 フィールドは、アイテムがコレクションに追加されたときに設定され、アイテムが削除されたときにクリアされます。

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;

// This class demonstrates one way to use the ChangeItemKey
// method to store objects with keys that can be changed. The
// ChangeItemKey method is used to keep the internal lookup
// Dictionary in sync with the keys of the stored objects.
//
// MutableKeys stores MutableKey objects, which have an Integer
// Key property that can be set. Therefore, MutableKeys inherits
// KeyedCollection(Of Integer, MutableKey).
//
public class MutableKeys : KeyedCollection<int, MutableKey>
{
    // This parameterless constructor delegates to the base class
    // constructor that specifies a dictionary threshold. A
    // threshold of 0 means the internal Dictionary is created
    // the first time an object is added.
    //
    public MutableKeys() : base(null, 0) {}

    protected override int GetKeyForItem(MutableKey item)
    {
        // The key is MutableKey.Key.
        return item.Key;
    }

    protected override void InsertItem(int index, MutableKey newItem)
    {
        if (newItem.Collection != null)
            throw new ArgumentException("The item already belongs to a collection.");

        base.InsertItem(index, newItem);
        newItem.Collection = this;
    }

    protected override void SetItem(int index, MutableKey newItem)
    {
        MutableKey replaced = Items[index];

        if (newItem.Collection != null)
            throw new ArgumentException("The item already belongs to a collection.");

        base.SetItem(index, newItem);
        newItem.Collection = this;
        replaced.Collection = null;
    }

    protected override void RemoveItem(int index)
    {
        MutableKey removedItem = Items[index];

        base.RemoveItem(index);
        removedItem.Collection = null;
    }

    protected override void ClearItems()
    {
        foreach( MutableKey mk in Items )
        {
            mk.Collection = null;
        }

        base.ClearItems();
    }

    internal void ChangeKey(MutableKey item, int newKey)
    {
        base.ChangeItemKey(item, newKey);
    }

    public void Dump()
    {
        Console.WriteLine("\nDUMP:");
        if (Dictionary == null)
        {
            Console.WriteLine("    The dictionary has not been created.");
        }
        else
        {
            Console.WriteLine("    Dictionary entries");
            Console.WriteLine("    ------------------");

            foreach( KeyValuePair<int, MutableKey> kvp in Dictionary )
            {
                Console.WriteLine("    {0} : {1}", kvp.Key, kvp.Value);
            }
        }

        Console.WriteLine("\n    List of items");
        Console.WriteLine("    -------------");

        foreach( MutableKey mk in Items )
        {
            Console.WriteLine("    {0}", mk);
        }
    }
}

public class Demo
{
    public static void Main()
    {
        MutableKeys mkeys = new MutableKeys();

        // The Add method is inherited from Collection.
        //
        mkeys.Add(new MutableKey(110072674, "Widget"));
        mkeys.Add(new MutableKey(110072675, "Sprocket"));

        mkeys.Dump();

        Console.WriteLine("\nCreate and insert a new item:");
        MutableKey test = new MutableKey(110072684, "Gear");
        mkeys.Insert(1, test);

        mkeys.Dump();

        try
        {
            Console.WriteLine("\nTry to insert the item again:");
            mkeys.Insert(1, test);
        }
        catch(ArgumentException ex)
        {
            Console.WriteLine("Error: {0}", ex.Message);
        }

        Console.WriteLine("\nChange the Key property of the item:");
        test.Key = 100000072;

        mkeys.Dump();

        try
        {
            Console.WriteLine("\nTry to set the Key property to an existing key:");
            test.Key = 110072674;
        }
        catch(ArgumentException ex)
        {
            Console.WriteLine("Error: {0}", ex.Message);
        }

        mkeys.Dump();
    }

    private static void Display(MutableKeys order)
    {
        Console.WriteLine();
        foreach( MutableKey item in order )
        {
            Console.WriteLine(item);
        }
    }
}

// This class has a key that can be changed.
//
public class MutableKey
{

    public MutableKey(int newKey, string newValue)
    {
        _key = newKey;
        Value = newValue;
    } //New

    public string Value;
    internal MutableKeys Collection;

    private int _key;
    public int Key
    {
        get
        {
            return _key;
        }
        set
        {
            if (Collection != null)
            {
                Collection.ChangeKey(this, value);
            }

            _key = value;
        }
    }

    public override string ToString()
    {
        return String.Format("{0,9} {1}", _key, Value);
    }
}

/* This code example produces the following output:

DUMP:
    Dictionary entries
    ------------------
    110072674 : 110072674 Widget
    110072675 : 110072675 Sprocket

    List of items
    -------------
    110072674 Widget
    110072675 Sprocket

Create and insert a new item:

DUMP:
    Dictionary entries
    ------------------
    110072674 : 110072674 Widget
    110072675 : 110072675 Sprocket
    110072684 : 110072684 Gear

    List of items
    -------------
    110072674 Widget
    110072684 Gear
    110072675 Sprocket

Try to insert the item again:
Error: The item already belongs to a collection.

Change the Key property of the item:

DUMP:
    Dictionary entries
    ------------------
    110072674 : 110072674 Widget
    110072675 : 110072675 Sprocket
    100000072 : 100000072 Gear

    List of items
    -------------
    110072674 Widget
    100000072 Gear
    110072675 Sprocket

Try to set the Key property to an existing key:
Error: An item with the same key has already been added.

DUMP:
    Dictionary entries
    ------------------
    110072674 : 110072674 Widget
    110072675 : 110072675 Sprocket
    100000072 : 100000072 Gear

    List of items
    -------------
    110072674 Widget
    100000072 Gear
    110072675 Sprocket
 */
Imports System.Collections.Generic
Imports System.Collections.ObjectModel

' This class demonstrates one way to use the ChangeItemKey
' method to store objects with keys that can be changed. The 
' ChangeItemKey method is used to keep the internal lookup
' Dictionary in sync with the keys of the stored objects. 
'
' MutableKeys stores MutableKey objects, which have an Integer
' Key property that can be set. Therefore, MutableKeys inherits
' KeyedCollection(Of Integer, MutableKey).
'
Public Class MutableKeys
    Inherits KeyedCollection(Of Integer, MutableKey)

    ' This parameterless constructor delegates to the base class 
    ' constructor that specifies a dictionary threshold. A
    ' threshold of 0 means the internal Dictionary is created
    ' the first time an object is added.
    '
    Public Sub New()
        MyBase.New(Nothing, 0)
    End Sub
    
    Protected Overrides Function GetKeyForItem( _
        ByVal item As MutableKey) As Integer

        ' The key is MutableKey.Key.
        Return item.Key   
    End Function

    Protected Overrides Sub InsertItem( _
        ByVal index As Integer, ByVal newItem As MutableKey)

        If newItem.Collection IsNot Nothing Then _
            Throw New ArgumentException("The item already belongs to a collection.")

        MyBase.InsertItem(index, newItem)
        newItem.Collection = Me
    End Sub

    Protected Overrides Sub SetItem(ByVal index As Integer, _
        ByVal newItem As MutableKey)

        Dim replaced As MutableKey = Items(index)

        If newItem.Collection IsNot Nothing Then _
            Throw New ArgumentException("The item already belongs to a collection.")

        MyBase.SetItem(index, newItem)
        newItem.Collection = Me
        replaced.Collection = Nothing
    End Sub

    Protected Overrides Sub RemoveItem(ByVal index As Integer)
        Dim removedItem As MutableKey = Items(index)

        MyBase.RemoveItem(index)
        removedItem.Collection = Nothing
    End Sub

    Protected Overrides Sub ClearItems()
        For Each mk As MutableKey In Items
            mk.Collection = Nothing
        Next
        
        MyBase.ClearItems()
    End Sub

    Friend Sub ChangeKey(ByVal item As MutableKey, _
        ByVal newKey As Integer)

        MyBase.ChangeItemKey(item, newKey)
    End Sub
    
    Public Sub Dump()
        Console.WriteLine(vbLf & "DUMP:")
        If Dictionary Is Nothing Then
            Console.WriteLine("    The dictionary has not been created.")
        Else
            Console.WriteLine("    Dictionary entries")
            Console.WriteLine("    ------------------")

            For Each kvp As KeyValuePair(Of Integer, MutableKey) In Dictionary
                Console.WriteLine("    {0} : {1}", kvp.Key, kvp.Value)
            Next
        End If

        Console.WriteLine(vbLf & "    List of items")
        Console.WriteLine("    -------------")

        For Each mk As MutableKey In Items
            Console.WriteLine("    {0}", mk)
        Next
    End Sub

End Class

Public Class Demo
    
    Public Shared Sub Main() 

        Dim mkeys As New MutableKeys()

        ' The Add method is inherited from Collection.
        '
        mkeys.Add(New MutableKey(110072674, "Widget"))
        mkeys.Add(New MutableKey(110072675, "Sprocket"))

        mkeys.Dump() 
    
        Console.WriteLine(vbLf & "Create and insert a new item:")
        Dim test As New MutableKey(110072684, "Gear")
        mkeys.Insert(1, test)

        mkeys.Dump()

        Try
            Console.WriteLine(vbLf & "Try to insert the item again:")
            mkeys.Insert(1, test)
        Catch ex As ArgumentException
            Console.WriteLine("Error: {0}", ex.Message)
        End Try

        Console.WriteLine(vbLf & "Change the Key property of the item:")
        test.Key = 100000072

        mkeys.Dump()

        Try
            Console.WriteLine(vbLf & "Try to set the Key property to an existing key:")
            test.Key = 110072674
        Catch ex As ArgumentException
            Console.WriteLine("Error: {0}", ex.Message)
        End Try

        mkeys.Dump()

    End Sub
    
    Private Shared Sub Display(ByVal order As MutableKeys) 
        Console.WriteLine()
        For Each item As MutableKey In  order
            Console.WriteLine(item)
        Next item
    End Sub
End Class

' This class has a key that can be changed.
' 
Public Class MutableKey

    Public Sub New(ByVal newKey As Integer, ByVal newValue As String)
        _key = newKey
        Value = newValue
    End Sub
    
    Public Value As String
    Friend Collection As MutableKeys
    
    Private _key As Integer
    Public Property Key As Integer 
        Get
            Return _key
        End Get
        Set
            If Collection IsNot Nothing Then
                Collection.ChangeKey(Me, value)
            End If

            _key = value
        End Set
    End Property

    Public Overrides Function ToString() As String 
        Return String.Format("{0,9} {1}", _key, Value)
    End Function
        
End Class

' This code example produces the following output:
'
'DUMP:
'    Dictionary entries
'    ------------------
'    110072674 : 110072674 Widget
'    110072675 : 110072675 Sprocket
'
'    List of items
'    -------------
'    110072674 Widget
'    110072675 Sprocket
'
'Create and insert a new item:
'
'DUMP:
'    Dictionary entries
'    ------------------
'    110072674 : 110072674 Widget
'    110072675 : 110072675 Sprocket
'    110072684 : 110072684 Gear
'
'    List of items
'    -------------
'    110072674 Widget
'    110072684 Gear
'    110072675 Sprocket
'
'Try to insert the item again:
'Error: The item already belongs to a collection.
'
'Change the Key property of the item:
'
'DUMP:
'    Dictionary entries
'    ------------------
'    110072674 : 110072674 Widget
'    110072675 : 110072675 Sprocket
'    100000072 : 100000072 Gear
'
'    List of items
'    -------------
'    110072674 Widget
'    100000072 Gear
'    110072675 Sprocket
'
'Try to set the Key property to an existing key:
'Error: An item with the same key has already been added.
'
'DUMP:
'    Dictionary entries
'    ------------------
'    110072674 : 110072674 Widget
'    110072675 : 110072675 Sprocket
'    100000072 : 100000072 Gear
'
'    List of items
'    -------------
'    110072674 Widget
'    100000072 Gear
'    110072675 Sprocket

注釈

が とCountitem等しい場合indexは、 の末尾に がKeyedCollection<TKey,TItem>追加されます。

このメソッドは O(n) 操作です。nCount です。

InsertItemは メソッドと Insert メソッドによってAdd呼び出されます。

実装側の注意

ジェネリック クラスから継承された メソッドと Insert メソッドのカスタマイズされた動作をAdd提供するには、このメソッドをCollection<T>オーバーライドします。

このメソッドの基底クラスの実装を呼び出して、基になるコレクションに項目を挿入し、ルックアップ ディクショナリを更新します。

適用対象

こちらもご覧ください