我发现这个方法可以改变一个列表,但我想要的是它返回新列表,我似乎无法弄清楚这是如何完成的。
这是我试过的
public static class Lists {
private static System.Random rng = new System.Random();
public static List<T> Shuffle<T>(this IList<T> list) {
int n = list.Count;
while(n > 1) {
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
return list;
}
}
它的意思是:
无法将
IList
转换为List
我想要的是该方法返回新的Shuffled
列表,但我无法让它返回列表。怎么办呢?
答案 0 :(得分:3)
IList
不一定是List
。您的方法返回List
,但会传递IList
:
public static List<T> Shuffle<T>(this IList<T> list) {
int n = list.Count;
while(n > 1) {
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
return list; //Still an IList!
}
最简单/最好的解决方案是返回IList<T>
而不是List<T>
。
public static IList<T> Shuffle<T>(this IList<T> list) {
如果确实需要实际列表,请致电ToList
:
return list.ToList(); //Now its a list
当然,这会比你需要的时间再次列举你的收藏。
答案 1 :(得分:1)
无法将List转换为IList
那是因为您有一个IList<T>
并且您正在返回List<T>
。您可以投射return (List<T>)list;
,但如果使用其他IList<T>
调用此内容,则会失败。
如果IList<T>
是只读的话,它也会失败。
然而,
我想要的是它返回新列表
嗯,这里没有新的清单。但我们很容易就是这样:
public static List<T> Shuffle<T>(this IList<T> source) {
List<T> list = new List<T>(source);
通过此更改,它现在会创建一个新列表,并在返回之前对其进行随机播放。
但是等等,为什么要将自己限制为IList<T>
作为输入?我们可以从任何IEnumerable<T>
创建一个新列表,为什么不这样做呢?
public static List<T> Shuffle<T>(this IEnumerable<T> source) {
List<T> list = new List<T>(source);
但是,有一个缺陷是Random
以非线程安全的方式用于非单线程代码。这也很容易改变,删除静态Random
并具有:
public static List<T> Shuffle<T>(this IEnumerable<T> source) {
List<T> list = new List<T>(source);
Random rng = new System.Random();
现在它没有错误,根据需要返回一个新的List,接受更广泛的输入,并且是线程安全的。
答案 2 :(得分:1)
首先,任何List
都自动为IList
。 List
必须实现IList
接口上定义的方法,因此根据定义,IList
。IList
。
但是您的代码被定义为接收IList
作为输入。这意味着您可以将任何实现List
接口的内容传递给它。因此,您可以将Dictionary
或SortedList
或ComboBoxListItems集合或IList
或任何实现List
的集合类型对象传递给它。因为你正在尝试&#34;当你没有被List
传递时,操纵并返回一个List
,编译器正在寻找它是否可以将你传递给IList
的内容转换为然后抱怨它可以&# 39;吨。实现IList
的大多数对象无法自动转换为List。
您的代码令人困惑,因为您传入的输入参数是List
,但名为 列表 。你应该解决这个问题。如果你想返回一个.ToList()
,你需要在你的方法中从传入的任何集合类型中创建一个。这就是public static class Lists {
private static System.Random rng = new System.Random();
public static List<T> Shuffle<T>(this IList<T> iList) {
var list = iList.ToList();
int n = list .Count;
while(n > 1) {
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
return list;
}
}
的用途。
IEnumerable<T>
但更好的是,您可能应该将输入参数键入IList<T>
,而不是public static class Lists {
private static System.Random rng = new System.Random();
public static List<T> Shuffle<T>(this IEnumerable<T> tEnumeration) {
var list = tEnumeration.ToList();
int n = list .Count;
while(n > 1) {
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
return list;
}
}
。您可以在任何枚举上执行ToList(),这样就可以在更广泛的潜在类型上使用您的方法。
LoginTable
答案 3 :(得分:0)
public static class Lists
{
public static IList<T> Shuffle<T>(this IList<T> list)
{
Random rng = new Random();
int n = list.Count;
while (n > 1)
{
n--;
int k = rng.Next(n + 1);
T value = list[k];
list[k] = list[n];
list[n] = value;
}
return list;
}
}
IList
作为返回类型答案 4 :(得分:-1)
我想要的是返回新Shuffled列表的方法,但是我不能让它返回列表。怎么办呢?
这不是您的代码所做的。你的代码将列表移动到位;它不会创建一个新的。
您可以像这样返回一个新的列表:
public static List<T> Shuffle<T>(this IList<T> list) {
return list.OrderBy(x => rng.Next()).ToList();
}
如果您确实想要对列表进行随机播放,则应该对参数和返回类型使用相同的类型。在您的情况下,由于您未使用List
特定内容,因此您应该使用IList
:
// Notice the I
public static IList<T> Shuffle<T>(this IList<T> list) {
// your code
}