【问题标题】:Implicit cast using Linq使用 Linq 进行隐式转换
【发布时间】:2015-12-01 14:23:41
【问题描述】:

假设我有一个整数列表 (var identifiers = Enumerable.Empty<int>())。

使用此列表,我可以将单个项目转换为另一种类型:

var castedIdentifiersLong = identifiers.Cast<long>();
var castedIdentifiersString = identifiers.Cast<string>();

我们可以使用Select&lt;TSource, TTarget&gt;() 来使用隐式转换:

var mappedIdentifiersLong = identifiers.Select<int, long>(x => x);
var mappedIdentifiersString = identifiers.Select<int, string>(x => x);

显然最后一条语句失败了,因为int 不能隐式转换为string。这是故意的。

有没有一种方法可以定义扩展方法(比如CastImplicitly&lt;T&gt;),我只能定义两个泛型类型中的一个,它会从源可枚举中找出第一个类型?

var unwanted = identifiers.ImplicitCast<string>();
var wanted = identifiers.ImplicitCast<long>();

在这种情况下,unwanted 甚至不应该编译,因为 int 不能隐式转换为 string。但另一方面,wanted 应该可以编译,因为它可以隐式转换为 long

【问题讨论】:

  • 你说的是TypeOf方法吗?
  • @Valentin 不,在这个表单中不存在一些编译时检查
  • var castedIdentifiersString = identifiers.Cast&lt;string&gt;(); 在非空 int 序列上崩溃,如果您开始枚举 castedIdentifiersString;目前尚不清楚您是否看到该问题
  • 不,这不是泛型类型推断的工作原理。它要么必须推断所有类型,要么必须指定所有类型。
  • @DanielCook 听起来更像是 OP 想要在编译时检查 Cast 不做的无效转换。

标签: c# .net extension-methods linq-to-objects


【解决方案1】:

有没有一种方法可以定义扩展方法(比如CastImplicitly&lt;T&gt;),我只能定义两个泛型类型之一,它会从源可枚举中找出第一个类型?

如果输入是通用的,则不会。编译器不能部分推断泛型参数 - 您必须指定所有泛型参数或不指定并让编译器推断。

即使你可以,编译器仍然不允许泛型类型之间的隐式转换。

如果您希望编译器在编译时识别无效转换,您可以进行显式转换:

var mappedIdentifiersString = identifiers.Select(x => (string)x);  // fails at compile time if x is an int.

它可能不会在编译时捕获每一个可能的无效转换(例如,在编译时总是允许转换到/来自object),但对于您的特定int,它确实会失败string 场景。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-23
    相关资源
    最近更新 更多