无法将项目添加到从IEnumerable中转换的IList / List

时间:2011-04-19 14:33:44

标签: c# list casting ienumerable

我正在尝试为我的老板创建一个小概念验证应用程序,但是我创建的代码模拟他试图启动的代码不起作用。

for (int i = 0; i < 5000; i++)
{
     ((IList<string>) obj2.Stuff).Add("Iteration " + i.ToString());
}

我试图在一行中将其全部删除,因为这是他们的代码在我们正在开发的框架中看起来的样子。 Anywho当上面的代码执行时,我得到一个运行时错误,说“Collection是固定大小的”。当我尝试转换为List而不是IList时,我得到一个InvalidCastException,说“无法将类型'System.String []'的对象转换为'System.Collections.Generic.List`1 [System.String]' 。“

任何人都有任何想法如何我可以拉出一个单线程序来向IEnumerable添加一个项目,或者帮我找出解决这两个错误的方法?提前谢谢。

编辑(4/19/2011美国东部时间上午10:49) 我正在添加更多代码来帮助人们 - 可能应该早点完成。遗憾。

的Program.cs:

        #region Cast Test
        Class1 obj2 = new Class1();
        obj2.Stuff = Enumerable.Empty<string>();

        Console.WriteLine("Cast - Start Time: " + 0 + "ms");

        Stopwatch stopwatch2 = new Stopwatch();
        stopwatch.Start();

        for (int i = 0; i < 5000; i++)
        {
            ((IList<string>) obj2.Stuff).Add("Iteration " + i.ToString());
        }

        stopwatch2.Stop();
        Console.WriteLine("Cast - Stop Time: " + stopwatch2.ElapsedMilliseconds.ToString() + "ms");
        #endregion

的Class1.cs:

public class Class1
{
    private IEnumerable<string> stuff;

    public IEnumerable<string> Stuff
    {
        get { return stuff; }
        set { stuff = value; }
    }
}

9 个答案:

答案 0 :(得分:2)

C#中的数组具有固定大小。您无法向其添加项目。

答案 1 :(得分:2)

您无法将string[]转换为IList<string>,因为string[]未实现该接口。您需要先创建一个实现IList<string>的对象:

List<string> list = obj2.Stuff.ToList();
for (int i = 0; i < 5000; i++)
{
     list.Add("Iteration " + i.ToString());
}

答案 2 :(得分:1)

为什么要在for循环中进行转换?虽然每个IList都是IEnumerable,但不是每个IEnumerable都是IList。您可以使用ToList扩展方法将IEnumerable复制到新列表。 (请确保using System.Linq;

此外,在此示例中,不需要for循环:

var list = obj2.Stuff.ToList();
new list.AddRange(Enumerable.Range(0, 5000).Select(i => "Iteration " + i.ToString()));

答案 3 :(得分:0)

IEnumerable并未提供与IList相同的功能。除非StuffIEnumerable IList,否则您的代码将无效。

第一个合同只承诺你可以一次迭代一个元素。它永远不会声明你可以添加新的元素。

当且仅当在运行时,您的可枚举对象也满足IList接口时,您才能将其关闭。

答案 4 :(得分:0)

您无法调用Add,因为obj2.Stuff似乎是一个数组,并且数组具有固定大小,如错误消息所示。

答案 5 :(得分:0)

类型System.String[]是一个字符串数组,它实现IEnumerable<string>不是一个List<string>。阵列具有固定长度。你为什么需要一行?

答案 6 :(得分:0)

将obj2.Stuff的类型更改为StringCollection或List。在.NET中,数组具有固定长度,您无法向它们添加新对象,因此请使用集合。

答案 7 :(得分:0)

由于obj2.Stuff是一个字符串数组,因此无法执行您要执行的操作。无法调整数组大小,因此无法向其中添加项目。

如果你可以用另一个数组替换obj2.Stuff中的数组,你可以从数组中获取数据并从中生成一个列表,将项添加到列表中,从列表中获取数据并创建一个数组从中,并使用它来替换原始数组:

List<string> items = new List<string>(obj2.Stuff);
for (int i = 0; i < 5000; i++) {
  items.Add("Iteration " + i.ToString());
}
obj2.Stuff = items.ToArray();

如果obj2.Stuff属性是只读的,那么除非将基础实现从数组更改为可以添加项目的集合,否则无法向其添加任何内容。

答案 8 :(得分:0)

在对上述答案之一的评论中,您说“我试图避免复制列表。”

您正在尝试将数据添加到基础类型为IEnumerable<T>的对象。但是IEnumerable对象不是实际的容器,它是一个接口。您无法向界面添加内容。但是您可以为其分配另一个实现该接口的对象。

因此,要使用上面的foson示例,您可以这样做:

obj2.Stuff = Enumerable.Range(0, 5000).Select(i => "Iteration " + i.ToString());

请注意,当此代码执行时,实际上没有发生。在实际迭代obj2.Stuff之前,不会创建任何对象。当发生这种情况时,将调用LINQ中的方法,这些方法一次创建一个对象并将它们返回到迭代器循环。

但这里没有涉及实际的存储设备。您可以迭代obj2.Stuff,除非您因此将每个整数添加到其他内容中,否则它们将在下一次迭代中消失。

这里的基本要点是你不能在IEnumerable中存储东西,而是IEnumerable是一种按顺序返回对象的方法,可以来自列表构造,也可以来自函数生成一个序列。