2013-03-01 116 views
8

在C#中,我试图从列表中获取随机索引中的项目。当它被取回时,我希望它被删除,以便它不能被选中。看起来好像我需要很多操作来做到这一点,是不是有一个功能,我可以简单地从列表中提取一个项目? RemoveAt(索引)函数是无效的。我希望有一个返回值。从列表中删除项目并同时获取项目

我在做什么:

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); 

我想这样做:

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); 

难道这样的 “removeAndGetItem” 功能存在吗?

+0

你不得不写你自己的 - 据我所知,只有Stack或Queue具有内置的这种功能。这需要线程安全吗? – 2013-03-01 09:13:35

+1

为什么不能得到你想要的新变量/列表? – Kaf 2013-03-01 09:14:29

回答

15

不,因为它违背了纯粹的功能礼仪,一种方法有副作用,或者返回一个有用的值(即不只是表示错误状态) - 从来都不是。

如果你想要的功能出现原子,就可以得到获取名单,这将阻止其他线程访问列表上的锁,而要修改它:

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

请记住,只有在同时调用RemoveAndGet时,锁定才会有所帮助。其他一些函数仍然可以修改列表,并且仍然会出现OutOfBoundsException。如下所述,可以考虑异常处理。 – mateuscb 2013-12-18 16:12:27

+2

关于命令和查询的第一部分是不正确的,'Add'具有副作用并且在同一个类上返回一个值......它也不总是实用的,例如以Stack为例,'Pop'有副作用并返回一个值。 (我喜欢命令和查询的想法,但是这个概念不是在.NET中强制执行的,并不总是你想要的) – 2015-05-17 11:30:53

+0

个人而言,我认为我的“有用”部分在绝大多数用例中,答案仍适用于从“添加”返回的值。 – RoadieRich 2015-05-17 14:35:22

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; 
    } 
} 

这些被称为extension methods,请致电new List<T>().RemoveAndGetItem(0)

相近的扩展方法考虑

异常与您通过索引处理,检查索引withing 0和列表在此之前的数。

+0

+1我想这跟带锁的其他答案是一样的。感谢您的异常处理说明。 – Eirik 2013-03-01 09:50:39

+0

@Eirik没有关于如果将无效索引传递给IList上的方法会发生什么的规范,所以我认为最好将参数验证留给列表实现。 对于你所知道的,一个自定义的IList实现可能会**出于任何原因**超出范围索引。 – RoadieRich 2013-03-01 10:04:52

+0

@RichardLovely这就是我说为什么要考虑的确切原因。另外,出于好奇,自定义列表有什么可能会期望超出范围的索引? – LukeHennerley 2013-03-01 10:07:49