【问题标题】:Generic method to cast one arbitrary type to another in c#在c#中将一种任意类型转换为另一种类型的通用方法
【发布时间】:2010-06-29 10:06:25
【问题描述】:

我想做这样的事情:

public static TResult MyCast<TSource, TResult>(TSource item)
{
    return (TResult)item;
}

不限制 TSource 或 TResult 并尽可能避免不必要的装箱。 编辑:我想强调一下,我想要一个简单的类型转换,而不是在这里详细的类型转换。铸造失败是完全可以的,比如stringint

使用 CLR 2.0 是否有任何明智的方法可以做到这一点?

编辑:这是一个简化版,所以没什么用,是的。 但考虑转换泛型集合,例如:

public static Dictionary<string, TResult> CastValues<TSource, TResult>(this Dictionary<string, TSource> dictionary)

在与我的同事讨论后,似乎没有简单的方法来实现这样的功能(如果可能的话),所以我陷入了针对不同情况的几种非常简单的方法的代码膨胀(即 up - 以及引用类型的向下转换和某些值类型的转换):(

太糟糕了,我不能使用 .NET 4.0 以及 dynamic 等优点。

【问题讨论】:

  • 看看stackoverflow.com/questions/2111280/…。可能会给你一些想法。
  • 谢谢,但这在我的情况下不是很有用。 :(
  • 实际上你应该庆幸你不能使用 .NET 4.0 和动态的,因为你所拥有的是糟糕的计划。您必须在没有通用基类的不同类型层次结构之间进行转换,这是一种非常糟糕的代码气味,并且再多的动态也无法隐藏它。
  • 考虑到我被遗留代码库困住,现在需要进行交叉调用,我宁愿拥有我的小型转换例程而不是重新实现它们。跨度>

标签: c# generics


【解决方案1】:

你可以这样做:

public static TResult MyCast<TSource, TResult>(TSource item)
{
    return (TResult)((object)item);
}

很想听听这有多糟糕。

【讨论】:

  • > 不限制 TSource 或 TResult 并尽可能避免不必要的装箱
【解决方案2】:

我认为您要解决的问题与您无法将一种类型的集合转换为另一种类型的集合的问题相同。 例如

类 Obj1
{}
类 Obj2:Obj1
{}
列表 srcList = GetList();
List castedList=(List) srcList;//这行不会编译

我在实际查看 CLR 代码方面做得并不多 但是,假设它就像 C++ 一样,您在这里所拥有的实际上是存储在集合中的不同值。换句话说,srcList 将包含一个指向 castedList 中对象 2 接口的指针列表,您将拥有一个指向对象 2 内对象 1 接口的指针。

为了解决这个问题,您需要让您的转换函数遍历集合中的每个项目。然而,为了能够遍历项目,列表必须实现某种枚举接口。所以枚举接口需要对强制转换函数进行约束。

因此答案是否定的。

但是,如果您准备通过限制 in 类型来实现这一点:

静态类 ListCast
其中 TSource:IEnumerable
其中 TResult:IList,new()
{
静态 TResult Cast(TSource 列表)
{
TResult castedList=newTResult();
foreach(列表中的 TtemType 项)
{
castedList.Add(TItemType)item);
}

     返回 castedList;
}
}

【讨论】:

  • 没关系。我不是在研究复杂的类型转换解决方案。我想要一个运行时类型转换,仅此而已。在这一点上,我很确定没有任何简单的解决方案。
【解决方案3】:

怎么会
x = MyCast&lt;SourceType, ResultType&gt;(y)

x = (ResultType)y 更有用吗?

【讨论】:

  • 通常您将其作为 MyCast(object input) 执行,因为您想在具有反射的通用调用中使用它以进行动态转换。我也看不出这种方法的原因。
  • 这是一个简化的例子。我的实际需要是这样的方法: public static Dictionary CastValues(this Dictionary dictionary)
  • @13xforever:使用 Cast 和 OfType 扩展方法怎么样?
  • @simendsjo:这仅适用于某些情况以及它们适用的情况,我显然不需要编写一些愚蠢的包装器来调用它们。
【解决方案4】:

TSourceTResult 都是引用类型时,这很简单。

如果一个或另一个是值类型,你希望它如何工作?值类型不能相互继承,所以这不是向上或向下转换的问题。您可能期望在intdouble 之间进行数字转换,但您必须自己编写这些代码:.NET 不会将它们视为类型转换。而在DateTimestring 之间的转换涉及更多的智能(什么格式?哪种文化?等等)。

如果您只是处理引用类型,那么此方法可以是单行的。如果您还想处理值类型,则需要为各种组合编写特殊情况代码。

编辑: Convert.ChangeType 在封装值类型之间的各种转换方面做得很合理。但是你提到你不想引入拳击:Convert.ChangeType 不是通用的,它需要一个object

【讨论】:

  • 我只对您通常在开发过程中执行的显式转换感兴趣(换句话说,我不希望它足够智能以在类型之间进行自定义转换)。即使考虑到引用类型,我也想不出一种可以同时执行向上和向下转换的方法(好吧,不是在 4.0 之前的 CLR 中)。总而言之,这就是我问的原因。现在,我为使用 ATM 的所有类型提供了自定义通用方法。它们都非常简单,并且做同样的事情。这只是......令人不安。
  • “您通常在开发过程中执行的显式转换” - 这些实际上是由 C# 编译器实现的规则。所有类型转换的语法都相同,但编译器知道如何在各种数字类型之间进行转换;它为不同的类型对生成不同的 IL。在您的 MyCast 方法中,您需要自己重新实现这些规则。
  • 是的,我知道。只是 .NET 4.0 中引入的 DLR 原型在某些时候是一个在 CLR 之上运行的单独项目,所以我认为也许有一种相当简单的方法来进行运行时转换。 :D
  • 嗯——Convert.ChangeType,但我想这也不理想。
  • 感谢Convert.ChangeType。即使它在这种特殊情况下没有多大用处,但它仍然是这里最有用的知识。
猜你喜欢
  • 1970-01-01
  • 2020-12-02
  • 2012-03-28
  • 2023-02-07
  • 2020-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多