2013-03-01 8 views
8

In C# Ich versuche, ein Element aus einer Liste an einem zufälligen Index zu erhalten. Wenn es abgerufen wurde, möchte ich, dass es entfernt wird, sodass es nicht mehr ausgewählt werden kann. Es scheint, als ob ich eine Menge Operationen brauche, um das zu tun, gibt es nicht eine Funktion, wo ich einfach einen Gegenstand aus der Liste extrahieren kann? Die RemoveAt (Index) -Funktion ist ungültig. Ich möchte eins mit einem Rückgabewert.Entfernen Sie das Element aus der Liste und rufen Sie das Element gleichzeitig

Was ich tue:

List<int> numLst = new List<int>(); 
numLst.Add(1); 
numLst.Add(2); 

do 
{ 
    int index = rand.Next(numLst.Count); 
    int extracted = numLst[index]; 
    // do something with extracted value... 
    numLst.removeAt(index); 
} 
while(numLst.Count > 0); 

Was möchte ich tun, um:

List<int> numLst = new List<int>(); 
numLst.Add(1); 
numLst.Add(2); 

do 
{ 
    int extracted = numLst.removeAndGetItem(rand.Next(numLst.Count)); 
    // do something with this value... 
} 
while(numLst.Count > 0); 

Gibt es eine solche "removeAndGetItem" -Funktion gibt es? Diese

+0

Du müss schreiben Ihr eigenes - soweit ich weiß, hat nur ein Stapel oder eine Warteschlange diese Art von Funktionalität eingebaut. Müsste das Thread-sicher sein? –

+1

Warum nicht bekommen, was Sie wollen, um eine neue Variable/Liste? – Kaf

Antwort

15

Nein, da es eine Verletzung der reinen Funktionsetikette ist, bei der eine Methode entweder einen Nebeneffekt hat oder einen nützlichen Wert liefert (d. H. Nicht nur einen Fehlerzustand anzeigt) - niemals beides.

Wenn Sie die Funktion erscheinen Atom wollen, können Sie eine Sperre auf der Liste erwerben bekommen, die anderen Threads den Zugriff auf die Liste zu stoppen, während Sie es ändern:

public static class Extensions 
{ 
    public static T RemoveAndGet<T>(this IList<T> list, int index) 
    { 
     lock(list) 
     { 
      T value = list[index]; 
      list.RemoveAt(index); 
      return value; 
     } 
    } 
} 
+0

Denken Sie daran, dass die Sperre nur hilft, wenn RemoveAndGet gleichzeitig aufgerufen wird. Einige andere Funktionen können die Liste noch ändern, und Sie hätten weiterhin OutOfBoundsException. Wie unten erwähnt, könnte die Ausnahmebehandlung in Betracht gezogen werden. – mateuscb

+2

der erste Teil über Befehle und Abfragen ist einfach nicht wahr, 'Add' hat Nebenwirkungen und gibt einen Wert auf die gleiche Klasse zurück ... es ist auch nicht immer praktisch, nimm einen Stack zum Beispiel,' Pop' hat Nebenwirkungen und gibt einen Wert zurück. das wäre seltsam, diese beiden getrennt zu halten .. (Ich mag die Idee von Befehlen und Abfragen, aber dieses Konzept wird nicht in .NET erzwungen und nicht immer was du willst) –

+0

Persönlich denke ich, dass der "nützliche" Teil meiner Die Antwort gilt immer noch für den zurückgegebenen Wert von 'Add', in der überwiegenden Mehrheit der Anwendungsfälle. – RoadieRich

5
public static class ListExtensions 
{ 
    public static T RemoveAndGetItem<T>(this IList<T> list, int iIndexToRemove} 
    { 
    var item = list[iIndexToRemove]; 
    list.RemoveAt(iIndexToRemove); 
    return item; 
    } 
} 

sind extension methods genannt, nennen als new List<T>().RemoveAndGetItem(0).

Dinge in der Verlängerung Methode

Exception Handling mit dem Index, den Sie passieren, überprüfen zu berücksichtigen, dass der Index vor dies zu tun 0 und die Zählung der Liste wird withing.

+0

+1 Ich denke, das ist das gleiche wie die andere Antwort mit dem Schloss. Danke für die Ausnahmebehandlungsnotiz. – Eirik

+0

@Eirik Es gibt keine Spezifikation darüber, was passiert, wenn Sie einen ungültigen Index an eine Methode in IList übergeben, daher ist es besser, die Argumentüberprüfung der Listenimplementierung zu überlassen. Nach allem, was Sie wissen, könnte eine benutzerdefinierte IList-Implementierung aus irgendeinem Grund * außerhalb des Bereichs liegende Indizes erwarten. – RoadieRich

+0

@RichardLovely dies ist der genaue Grund, warum ich sagte, es ist "etwas zu beachten". Auch, welche Möglichkeit könnte eine benutzerdefinierte Liste aus Neugier einen Index erwarten, der außer Reichweite ist? – LukeHennerley

Verwandte Themen