Sdílet prostřednictvím


KeyedCollection<TKey,TItem>.RemoveItem(Int32) Metoda

Definice

Odebere prvek v zadaném indexu objektu KeyedCollection<TKey,TItem>.

protected:
 override void RemoveItem(int index);
protected override void RemoveItem (int index);
override this.RemoveItem : int -> unit
Protected Overrides Sub RemoveItem (index As Integer)

Parametry

index
Int32

Index prvku, který se má odebrat.

Příklady

Tato část obsahuje dva příklady kódu, které ukazují přepsání RemoveItem metody tak, aby poskytovala vlastní chování pro odebrání objektů z kolekce. První příklad přidá vlastní oznámení události a druhý zajišťuje podporu pro kolekci objektů s proměnlivými klíči.

Příklad 1

Následující příklad kódu ukazuje, jak přepsat chráněné InsertItemmetody , RemoveItem, ClearItemsa SetItem k poskytnutí vlastního Addchování pro metody , Removea Clear a pro nastavení výchozí Item[] vlastnosti (indexer v jazyce C#). Vlastní chování uvedené v tomto příkladu je událost oznámení s názvem Changed, která je vyvolána na konci každé přepsané metody.

Příklad kódu vytvoří SimpleOrder třídu, která je odvozena z KeyedCollection<TKey,TItem> a představuje jednoduchý formulář objednávky. Formulář objednávky obsahuje OrderItem objekty představující položky seřazené. Příklad kódu také vytvoří SimpleOrderChangedEventArgs třídu, která obsahuje informace o události, a výčet pro identifikaci typu změny.

Příklad kódu demonstruje vlastní chování voláním vlastností a metod odvozené třídy v Main metodě Demo třídy .

Tento příklad kódu používá objekty s neměnnými klíči. Příklad kódu, který používá proměnlivé klíče, najdete v tématu 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.

Příklad 2

Následující příklad kódu ukazuje, jak přepsat chráněnou ChangeItemKey metodu tak, aby podporovala měnitelné klíče, a jak přepsat chráněné ClearItemsInsertItemRemoveItem, , a SetItem metody pro zachování integrity klíčů a kolekce.

Příklad kódu vytvoří kolekci MutableKeys , která je odvozena od KeyedCollection<TKey,TItem>třídy a MutableKey . Třída MutableKey má nastavitelnou Key vlastnost. Když je k vlastnosti přiřazen nový klíč, setter vlastností volá metodu internal (Friend v jazyce Visual Basic) ChangeKey kolekce k otestování, zda nový klíč bude v konfliktu s existujícím klíčem. V takovém případě je vyvolána výjimka a hodnota vlastnosti se nezmění.

Aby bylo možné zachovat spojení mezi objektem MutableKey a kolekcí MutableKeys a zabránit vložení objektu do dvou kolekcí, MutableKeyinternal třída pole (Friend v jazyce Visual Basic). Collection Toto pole je udržováno chráněnými metodami, které poskytují vlastní chování pro přidávání a odebírání položek z kolekce, jako InsertItem je například metoda . Pole je nastaveno, když je položka přidána do kolekce, a vymazáno, když je položka odebrána.

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

Poznámky

Klíč elementu je také odebrán z vyhledávacího slovníku.

Pokud počet prvků překročil prahovou hodnotu vytvoření slovníku KeyedCollection<TKey,TItem> a používá vyhledávací slovník, bude nadále používat vyhledávací slovník, i když počet prvků je opět pod prahovou hodnotou.

Tato metoda je operace O(n), kde n je Count.

Poznámky pro implementátory

Přepište tuto metodu tak, aby poskytovala přizpůsobené chování pro Remove(T) metody a RemoveAt(Int32) zděděné z Collection<T> obecné třídy a Remove(TKey) metody .

Voláním implementace základní třídy této metody odeberete položku z podkladové kolekce a aktualizujete vyhledávací slovník.

Platí pro

Viz také