【问题标题】:In C# can you up-cast an object type to a collection type of generic "object"s在 C# 中,您可以将对象类型转换为通用“对象”的集合类型吗
【发布时间】:2018-06-07 11:50:25
【问题描述】:

被否决后的免责声明:

简而言之,最初的问题是,当返回 myObject 时,它是一个 object 类型,在一种情况下可以转换为 HashSet<Availability>,但在另一种情况下可以转换为 HashSet<Contact>,等等.

我想遍历 myObject 集合中的对象,无论它们是 Availability 对象、Contact 对象还是其他对象。

我们确实找到了解决方案,并以额外的智慧来解释为什么这是一个让自己陷入困境的恶臭。非常感谢社区。​​p>

根据 cmets,您会发现原始问题做出了不正确的技术假设。我把它留在下面并保持不变,作为任何可能与我有同样误解的人的学习机会。

原始问题如下:


我有一个object 类型的对象,如果我在其上调用GetType(),则在一种情况下返回HashSet<Availability> 类型,但在另一种情况下返回不相关类型的HashSet<Contact>,或任何数字未知的HashSet<...> 类型。

object myObject = getMyObject();
myObject.GetType() // = HashSet<Availability>

我想将对象向上转换为某种类型的集合(HashSet 或其他),同时将集合的泛型类型向下转换为对象,这样代码就不必知道在编译时间。

object myObject = getMyObject();
myObject.GetType() // = HashSet<Availability>
var myUsefulObject = (HashSet<object>)myObject;

当我尝试这个时,我得到一个“无法投射...”异常。

这可能吗? 如果有,怎么做?

我相信我拥有的 HashSet 类型和我想要的类型之间存在协变,但是因为我的 initial 类型只是一个对象,所以我无法做到 this stack-overflow answer suggests

【问题讨论】:

  • 这可能吗? -- 不,这一切都是梦。编译器并没有真正告诉您您对协方差的看法是错误的,而且您所做的事情与您链接的答案中的内容有深刻的根本不同是无关紧要的。
  • 看,假设您可以将HashSet&lt;Availability&gt; 转换为HashSet&lt;object&gt;。然后你可以这样做:(new HashSet&lt;Availability&gt;() as HashSet&lt;object&gt;).Add("LOL")。你觉得这是个好主意吗?
  • 我通常发现这样的问题是 XY 问题,这种演员阵容有什么好处?
  • @David 这里没有HashSet&lt;object&gt;。你有一个HashSet&lt;Availability&gt;,它不是 HashSet&lt;object&gt;。这个问题与HashSet&lt;object&gt; 无关,因为HashSet&lt;object&gt;HashSet&lt;Availability&gt; 是两个完全不相关的类,它们恰好以相同的方式生成。我告诉过你为什么编译器不会进行转换。
  • 所以询问代表,而不是这个。这是一个闻起来很糟糕的解决方法! :)

标签: c# types casting type-conversion covariance


【解决方案1】:

正如您问题下的长链 cmets 所示 - 您不能将 HashSet&lt;Availability&gt; 转换为 HashSet&lt;object&gt;,因为这两种类型之间没有定义隐式\显式\任何其他转换。但是,HashSet&lt;T&gt; 实现了几个协变接口,例如IReadOnlyCollection&lt;T&gt;IEnumerable&lt;T&gt;,您可以将HashSet&lt;Availability&gt; 转换为这些接口(@98​​7654327@):

object myObject = getMyObject();
var myUsefulObject = (IReadOnlyCollection<object>)myObject;

如果T 类型在接口中是协变的 - 此类型不能用作该接口中任何方法的参数,只能用作返回类型。这意味着在这种情况下所有可能破坏类型安全的方法(例如Add(T item)Remove(T item) 等)都不能出现在此类接口中,并且将Availability 作为object 返回不是问题。

【讨论】:

  • 这很漂亮。 object propValue = propertyInfo.GetValue(baseModel); if (propValue is IEnumerable o) { object result = ((IReadOnlyCollection&lt;object&gt;)o).First();
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-02
  • 1970-01-01
  • 2013-01-09
  • 1970-01-01
  • 1970-01-01
  • 2020-01-09
相关资源
最近更新 更多