我有一个带有大多数基类型的隐式转换运算符的类型,并尝试在此类型的集合上使用.Cast<string>()
,但失败了。当我挖掘它时,我注意到通过as
进行的转换不会使用隐式或显式转换而只是不会编译,所以我猜这是.Cast
落下的地方。所以这失败了
var enumerable = source.Cast<string>();
但这有效
var enumerable = source.Select(x => (string)x);
那么Cast的好处是什么?当然,这是几个字符较短,但似乎更有限。如果它可以用于转换,除了更紧凑的语法之外还有其他一些好处吗?
答案 0 :(得分:42)
当您的集合仅实现Cast
(即非通用版本)时,IEnumerable
的好处就出现了。在这种情况下,Cast
会通过转换将所有元素转换为TResult
,并返回IEnumerable<TResult>
。这很方便,因为所有其他LINQ扩展方法(包括Select
)仅针对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
答案 1 :(得分:5)
我检查了Cast<TResult>
IEnumerable
,它是实现(非通用)ArrayList
接口的类型的扩展方法。
它可以将未实现IEnumerable<T>
的集合类(例如Select<T>
)转换为可以执行的集合类,从而允许执行更丰富的操作(例如{{1}})它