我有一个包含对大多数基本类型进行隐式转换运算符的类型,并试图在此类型的集合上使用.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());
CastOfType是为IEnumerable定义的仅有的两种LINQ扩展方法。 OfType的工作方式类似于Cast,但会跳过不是TResult类型的元素,而不会引发异常。

强制转换和隐式转换

使用Cast时隐式转换运算符不起作用的原因很简单:Castobject转换为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

08-26 19:53
查看更多