snr*_*snr 5 c# casting type-conversion
如果错误无法将 object of type 转换System.Int64为 typeSystem.Int32,我会理解这是由于数据缩小的可能性。但是,我不明白为什么会出现错误,无法将 type 的 object 强制转换System.Int32为 typeSystem.Int64,尽管范围long更高。
int[] integers = { 1, 2, 3 };
IEnumerable<long> test1 = integers.OfType<long>();
IEnumerable<long> test2 = integers.Cast<long>();
foreach (var l in test2) ;
Run Code Online (Sandbox Code Playgroud)
Cast 与 Convert 不同。 Int32->Int64是语义无损转换。许多 C# 类型使用用户定义的转换运算符重载 '(type)'转换运算符,并在不允许类型转换的情况下实际执行转换。
C# 语言将为您生成一个隐式转换,用于常见和安全的代码模式,例如:
int num = 2147483647;
long bigNum = num;
Run Code Online (Sandbox Code Playgroud)
但是这些是类型转换要求对象可分配给目标类型的变量的规则的例外。另一个例外是类型的表达式object可以强制转换为任何类型,并且如果对象不能分配给该类型的变量,则会在运行时失败。
Enumerable.Cast<T>完全按照它说的做,并对集合中的每个元素执行 Cast。不是转换,即使类型实现了用户定义的转换运算符。这是因为强制转换是 from objectto T,从而绕过任何用户定义的转换运算符或 C# 隐式转换。
来源:
public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source)
{
IEnumerable<TResult> typedSource = source as IEnumerable<TResult>;
if (typedSource != null) return typedSource;
if (source == null) throw Error.ArgumentNull("source");
return CastIterator<TResult>(source);
}
static IEnumerable<TResult> CastIterator<TResult>(IEnumerable source) {
foreach (object obj in source) yield return (TResult)obj;
}
Run Code Online (Sandbox Code Playgroud)
请注意, 的参数Cast<T>是Enumerable,不是Enumberable<TSource>。此 API 的目的是为非通用集合提供适配器。在 .NET 中引入泛型之前(请注意,它们不仅仅是一种语言功能),Enumerable是基本集合类型,并且要在 LINQ 中使用较旧的集合,必须将它们转换为IEnumerable<T>.
即使此 API 的目标是应用用户定义的转换或隐式转换,在 C# 中也没有明显的方法来实现它。C# 泛型不是模板*,泛型方法将有一个必须遵循 C# 规则的实现。EG这样的事情;
public static IEnumerable<TDest> MyCast<TDest, TSource>(this IEnumerable<TSource> col)
{
foreach (var s in col)
yield return (TDest)s;
}
Run Code Online (Sandbox Code Playgroud)
无法编译,因为编译器无法验证是否可从 TSource 类型的对象分配 TDest。因此,您必须首先将每个项目强制转换object,这正是采用非通用 IEnumerable 的版本中发生的情况。
你可以写类似的东西
yield return (TDest)Convert.ChangeType(s, typeof(TDest));
Run Code Online (Sandbox Code Playgroud)
但是方法应该是:
public static class MyConvertExtension
{
public static IEnumerable<TDest> Convert<TDest, TSource>(this IEnumerable<TSource> col)
{
foreach (var s in col)
yield return (TDest)Convert.ChangeType(s, typeof(TDest));
}
}
Run Code Online (Sandbox Code Playgroud)
C++ 允许可能对模板中的所有类型参数都无效的代码,然后检查用作类型参数的特定类型。C# 要求类中的代码以这样的方式编写,即它可以与满足约束的任何类型一起使用。例如,在 C++ 中,可以编写一个函数,在类型参数的对象上使用算术运算符 + 和 -,这将在实例化模板时产生错误,类型不支持这些运算符。C# 不允许这样做;唯一允许的语言结构是那些可以从约束中推导出来的语言结构。