Try the following code
请尝试以下代码
public enum Color
{
Blue=1,
Red=2,
Green=3
}
public List<Color> ConvertColorEnum()
{
var intColor = new List<int>(){1,2,3};
return intColor.Cast<Color>().ToList();
}
Do you think the ConvertColorEnum()
will return a list of color, i.e., List<Color>(){Color.Blue, Color.Red, Color.Green}
?
你认为ConvertColorEnum()会返回一个颜色列表,即List
I tested this on 2 machines, one with .net 3.5 ( mscorlib version 2.0.50727.1433), another with .net 3.5 SP1 ( mscorlib version 2.0.50727.3082). The results were different-- the .net 3.5 threw an InvalidCastException
because couldn't convert integer to enum, whereas .net 3.5 SP1 could run successfully, with correct results returned.
我在2台机器上进行了测试,一台使用.net 3.5(mscorlib版本2.0.50727.1433),另一台使用.net 3.5 SP1(mscorlib版本2.0.50727.3082)。结果不同 - .net 3.5抛出InvalidCastException,因为无法将整数转换为枚举,而.net 3.5 SP1可以成功运行,返回正确的结果。
Anyone would like to try this on his/her machine and report the result or explain why this is so?
任何人都想在他/她的机器上试试并报告结果或解释为什么会这样?
3 个解决方案
#1
You can read about the difference between the SP1 and the original release of the .net 3.5 framework in the release notes.
您可以在发行说明中了解SP1与.net 3.5框架的原始发行版之间的区别。
Here's what it says for this particular issue:
以下是针对此特定问题的说法:
In LINQ query expressions over non-generic collections such as System.Collections.ArrayList, the from clause of the query is rewritten by the compiler to include a call to the Cast operator. Cast converts all element types to the type specified in the from clause in the query. In addition, in the original release version of Visual C# 2008, the Cast operator also performs some value type conversions and user-defined conversions. However, these conversions are performed by using the System.Convert class instead of the standard C# semantics. These conversions also cause significant performance issues in certain scenarios. In Visual C# 2008 SP1, the Cast operator is modified to throw an InvalidCastException for numeric value type and user-defined conversions. This change eliminates both the non-standard C# cast semantics and the performance issue. This change is illustrated in the following example.
在非泛型集合(如System.Collections.ArrayList)上的LINQ查询表达式中,编译器会重写查询的from子句,以包含对Cast运算符的调用。 Cast将所有元素类型转换为查询中from子句中指定的类型。此外,在Visual C#2008的原始发行版中,Cast运算符还执行一些值类型转换和用户定义的转换。但是,这些转换是使用System.Convert类而不是标准C#语义执行的。这些转换在某些情况下也会导致严重的性能问题。在Visual C#2008 SP1中,Cast运算符被修改为针对数值类型和用户定义的转换抛出InvalidCastException。此更改消除了非标准C#强制语义和性能问题。以下示例说明了此更改。
You can also get more details in this blog post.
您还可以在此博客文章中获取更多详细信息。
#2
If you want it to work either way, use Select
instead.
如果您希望它以任何一种方式工作,请改用Select。
return intColor.Select(i=>(Color)i).ToList();
As for the why...?
至于为什么......?
#3
The Cast extension method makes use of an iterator which, on move next, stores the output of the original enumerator in an object variable (so boxing as needed) then attempts to cast that to the result type.
Cast扩展方法使用迭代器,在接下来的移动中,将原始枚举器的输出存储在对象变量中(因此根据需要进行装箱)然后尝试将其转换为结果类型。
Value types in boxed form do not respond to the cast operation in the same way they would if they were unboxed (where various automatic conversions are possible) instead they only allow casting to their original unboxed form.
盒装形式的值类型不会像取消装箱时那样响应转换操作(可以进行各种自动转换),而只允许转换为原始的未装箱形式。
I would imagine that the previous implementation of the Cast extension was either doing it completely differently or had some special casing for enum types to convert to an integral form (this is tricky as you must deal with all possible forms)
我可以想象,Cast扩展的先前实现要么完全不同,要么为枚举类型转换为整数形式有一些特殊的大小写(这很棘手,因为你必须处理所有可能的形式)
Marc's answer as to the correct solution is completely correct and is actually more efficient than the cast anyway for the aforementioned boxing reasons.
Marc关于正确解决方案的答案是完全正确的,并且实际上比上述拳击原因更有效。
#1
You can read about the difference between the SP1 and the original release of the .net 3.5 framework in the release notes.
您可以在发行说明中了解SP1与.net 3.5框架的原始发行版之间的区别。
Here's what it says for this particular issue:
以下是针对此特定问题的说法:
In LINQ query expressions over non-generic collections such as System.Collections.ArrayList, the from clause of the query is rewritten by the compiler to include a call to the Cast operator. Cast converts all element types to the type specified in the from clause in the query. In addition, in the original release version of Visual C# 2008, the Cast operator also performs some value type conversions and user-defined conversions. However, these conversions are performed by using the System.Convert class instead of the standard C# semantics. These conversions also cause significant performance issues in certain scenarios. In Visual C# 2008 SP1, the Cast operator is modified to throw an InvalidCastException for numeric value type and user-defined conversions. This change eliminates both the non-standard C# cast semantics and the performance issue. This change is illustrated in the following example.
在非泛型集合(如System.Collections.ArrayList)上的LINQ查询表达式中,编译器会重写查询的from子句,以包含对Cast运算符的调用。 Cast将所有元素类型转换为查询中from子句中指定的类型。此外,在Visual C#2008的原始发行版中,Cast运算符还执行一些值类型转换和用户定义的转换。但是,这些转换是使用System.Convert类而不是标准C#语义执行的。这些转换在某些情况下也会导致严重的性能问题。在Visual C#2008 SP1中,Cast运算符被修改为针对数值类型和用户定义的转换抛出InvalidCastException。此更改消除了非标准C#强制语义和性能问题。以下示例说明了此更改。
You can also get more details in this blog post.
您还可以在此博客文章中获取更多详细信息。
#2
If you want it to work either way, use Select
instead.
如果您希望它以任何一种方式工作,请改用Select。
return intColor.Select(i=>(Color)i).ToList();
As for the why...?
至于为什么......?
#3
The Cast extension method makes use of an iterator which, on move next, stores the output of the original enumerator in an object variable (so boxing as needed) then attempts to cast that to the result type.
Cast扩展方法使用迭代器,在接下来的移动中,将原始枚举器的输出存储在对象变量中(因此根据需要进行装箱)然后尝试将其转换为结果类型。
Value types in boxed form do not respond to the cast operation in the same way they would if they were unboxed (where various automatic conversions are possible) instead they only allow casting to their original unboxed form.
盒装形式的值类型不会像取消装箱时那样响应转换操作(可以进行各种自动转换),而只允许转换为原始的未装箱形式。
I would imagine that the previous implementation of the Cast extension was either doing it completely differently or had some special casing for enum types to convert to an integral form (this is tricky as you must deal with all possible forms)
我可以想象,Cast扩展的先前实现要么完全不同,要么为枚举类型转换为整数形式有一些特殊的大小写(这很棘手,因为你必须处理所有可能的形式)
Marc's answer as to the correct solution is completely correct and is actually more efficient than the cast anyway for the aforementioned boxing reasons.
Marc关于正确解决方案的答案是完全正确的,并且实际上比上述拳击原因更有效。