我有一个包含对大多数基本类型进行隐式转换运算符的类型,并试图在此类型的集合上使用.Cast<string>()
,但失败了。在我研究它的过程中,我注意到通过as
进行的转换不使用隐式或显式转换,并且不会进行编译,所以我猜这就是.Cast
崩溃的地方。所以这失败了
var enumerable = source.Cast<string>();
但这有效
var enumerable = source.Select(x => (string)x);
那么Cast的好处是什么?当然,它的字符短了几个,但似乎限制了很多。如果可以将其用于转换,那么除了更紧凑的语法之外,还有其他好处吗?
最佳答案
类型转换用法
当您的集合仅实现Cast
(即非通用版本)时,就可以享受IEnumerable
的好处。在这种情况下,Cast
通过强制转换将所有元素转换为TResult
,并返回IEnumerable<TResult>
。这很方便,因为仅为Select
声明了所有其他LINQ扩展方法(包括IEnumerable<T>
)。在代码中,它看起来像这样:
IEnumerable source = // getting IEnumerable from somewhere
// Compile error, because Select is not defined for IEnumerable.
var results = source.Select(x => ((string)x).ToLower());
// This works, because Cast returns IEnumerable<string>
var results = source.Cast<string>().Select(x => x.ToLower());
Cast
和OfType
是为IEnumerable
定义的仅有的两种LINQ扩展方法。 OfType
的工作方式类似于Cast
,但会跳过不是TResult
类型的元素,而不会引发异常。强制转换和隐式转换
使用
Cast
时隐式转换运算符不起作用的原因很简单:Cast
将object
转换为TResult
-且未为object
定义转换,仅针对您的特定类型。 Cast
的实现是这样的:foreach (object obj in source)
yield return (TResult) obj;
这种进行转换的“失败”对应于基本转换规则-如本例所示:
YourType x = new YourType(); // assume YourType defines an implicit conversion to string
object o = x;
string bar = (string)x; // Works, the implicit operator is hit.
string foo = (string)o; // Fails, no implicit conversion between object and string