我真的只是将字符串数据类型放入IEnumerable <int> </int>

时间:2010-11-10 20:15:48

标签: c# linq casting

好的,这有点奇怪。忽略我想做的事情,看看在这种情况下会发生什么的结果。

守则:

static string rawNumbers="1,4,6,20,21,22,30,34";
static IEnumerable<int> numbers = null;

static void Main(string[] args)
{
    numbers = rawNumbers.Split(',').Cast<int>();

    for (int i = 0; i < numbers.Count(); i++)
    {
        //do something
    }

}

情况:

numbers = rawNumbers.Split(',').Cast<int>(); 出现以便工作,并且不会抛出任何异常。但是,当我遍历集合时,抛出InvalidCastException。

现在,深入了解源代码并查看CastIterator<TResult>。这似乎是在for (int i = 0; i < numbers.Count(); i++) ...专门numbers.Count()

调用的
static IEnumerable<TResult> CastIterator<TResult>(IEnumerable source) {
    foreach (object obj in source) yield return (TResult)obj; 
}

错误发生在演员表上,当我查看source变量中的数据时,它是一个字符串[]。

我原本以为,因为我将成功调用强制转换成int的行所以一切都很好。幕后发生了什么?字符串数组真的只是存储在某个地方,并且在被调用之前没有被转换为T吗?懒惰的铸造也许?


我知道我不能这样做:(int)“42”。我的问题不是如何使演员工作,而是发生了什么。演员的延期执行?我称之为Cast<int>()的行似乎很奇怪,但实际上并没有。

5 个答案:

答案 0 :(得分:24)

有几件事:第一,你不能施放 stringint。您可以解析字符串并获得结果整数。但基本上你是在尝试这样做:

int x = (int)"32";

这是一个例外。 其次,LINQ运算符是延迟执行的,所以在你尝试迭代结果之前没有实际发生,那就是真正的工作开始时。

使用延迟执行时,不会检查您请求的操作是有效还是可以正确执行,它只是设置操作,然后尝试在迭代时单独执行。

答案 1 :(得分:8)

正如已经指出的那样,'延期执行'是这里的问题。在迭代结果变量之前,许多LINQ运算符不会导致lambda代码实际执行。

这样做的一个原因是允许您构建一系列可以一次执行的复杂操作,而不是作为一系列单独的操作。这可能是一件有用的事情 - 但如果你不期待它也会很棘手。

答案 2 :(得分:5)

Cast似乎有用的原因是因为调用方法时不会枚举IEnumerable,而是在调用Count()时。所以,对Cast()的调用确实没有做任何事情。一旦实际评估了Cast,代码就会失败。

而不是尝试施放,只需进行简单的转换。

numbers = rawNumbers.Split(',').Select(str => int.parse(str));

答案 3 :(得分:5)

您在Cast<int>()行没有立即收到错误的原因是因为记住这只是链接操作序列。只有在遍历集合后,才会执行转换。

rawNumbers.Split(',')马上发生,但Cast<int>()是延迟计算。

如果在该行上添加了ToList()或ToArray(),它将立即执行。

答案 4 :(得分:-1)

我可能错了,但我想知道它是否与int和string之间的转换有关。当我忘记你不能使用(int)来对抗字符串时,我总是会遇到错误,而你必须使用int.Parse。它可能与此有关,但这只是我的头脑。