简体   繁体   English

在c#中将一个任意类型转换为另一个类型的通用方法

[英]Generic method to cast one arbitrary type to another in c#

I want to do something like this: 我想做这样的事情:

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

Without restrictions on TSource or TResult and avoiding unnecessary boxing if possible. 没有TSource或TResult的限制,并尽可能避免不必要的拳击。 Edit : I want to stress out, that I want a simple casting of types, not elaborate type conversion here. 编辑 :我想强调一下,我想要一个简单的类型转换,而不是精心设计的类型转换。 It would be perfectly ok to fail at casting, say string to int . 在转换时失败是完全可以的,比如说stringint

Is there any sane way to do this using CLR 2.0? 有没有理智的方法来使用CLR 2.0做到这一点?

Edit : this is a simplified version, so it's pretty useless, yes. 编辑 :这是一个简化版本,所以它没用,是的。 But consider casting generic collections, such as this: 但考虑转换泛型集合,例如:

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

After some discussions with my co-workers, it seems like there's no simple way to implement such a feature (if at all possible), so I'm stuck with code bloat of several very simple methods for different situations (ie up- and downcast of reference types and casting of some value types) :( 在与我的同事讨论之后,似乎没有简单的方法来实现这样的功能(如果可能的话),所以我遇到了几种非常简单的方法,用于不同情况(即向上和向下)的代码膨胀引用类型和某些值类型的转换):(

Too bad I can't use .NET 4.0 with all it's dynamic et al goodness. 太糟糕了,我无法使用.NET 4.0,它具有dynamic等优点。

How would 怎么会
x = MyCast<SourceType, ResultType>(y)
be any more useful than 比任何更有用
x = (ResultType)y ? x = (ResultType)y

This is straightforward when TSource and TResult are both reference types. TSourceTResult都是引用类型时,这很简单。

If one or the other are value types, how do you want it to work? 如果其中一个是值类型,您希望它如何工作? Value types can't inherit from each other, so it's not a matter of doing an up- or down-cast. 值类型不能相互继承,因此不需要进行向上或向下转换。 You might expect numeric conversions between, say, int and double , but you'd have to code these yourself: .NET doesn't treat them as typecasts. 您可能期望在intdouble之间进行数字转换,但您必须自己编写代码:.NET不会将它们视为类型转换。 And conversion between, say, DateTime and string involves more intelligence (what format? which culture? etc.). 比如, DateTimestring之间的转换涉及更多的智能(什么格式?哪种文化?等等)。

If you're just handling reference types then this method can be a one-liner. 如果你只是处理参考类型,那么这个方法可以是一个单行。 If you want to handle value types as well then you'll need to write special case code for the various combinations. 如果你想处理值类型,那么你需要为各种组合编写特殊的案例代码。

Edit: Convert.ChangeType does a reasonable job at encapsulating the various conversions between value types. 编辑: Convert.ChangeType在封装值类型之间的各种转换方面做了一个合理的工作。 However you mentioned you're keen not to introduce boxing: Convert.ChangeType isn't generic and it takes an object . 但是你提到你不想引入装箱: Convert.ChangeType不是通用的,它需要一个object

I think that the problem you are trying to solve is the same as the problem that you cannot cast a collection of one type to a collection of another type. 我认为您尝试解决的问题与您无法将一种类型的集合转换为另一种类型的集合的问题相同。 eg 例如

class Obj1 等级Obj1
{} {}
class Obj2:Obj1 Obj2类:Obj1
{} {}
List<Obj2> srcList = GetList(); List <Obj2> srcList = GetList();
List<Obj1> castedList=(List<Obj2>) srcList;//this line wont compile List <Obj1> castedList =(List <Obj2>)srcList; //这行不会编译

I have not done much at actually looking at the CLR code However on the asuumption that it is like C++ what you would have here is actually different values stored in the collection. 我在实际查看CLR代码时没有做太多工作但是,假设它就像C ++一样,你在这里拥有的实际上是存储在集合中的不同值。 In other words srcList would contain a list of pointers to object 2's interface in castedList you would have a pointer to the the interface of the object 1's within object 2. 换句话说,srcList将包含指向castedList中对象2接口的指针列表,您将拥有指向对象2内对象1的接口的指针。

In order to resolve this you would need to have your casting function iterate through each of the items within the collection. 为了解决这个问题,您需要让您的转换函数遍历集合中的每个项目。 However in order to be able to iterate through the items the list would have to implement some sort of enumeration interface. 但是,为了能够遍历项目,列表必须实现某种枚举接口。 So the enumeration interface would need to be a constraint on the casting function. 因此枚举接口需要是对转换函数的约束。

So the answer would therefore be no. 所以答案是否定的。

However if you were prepared to implement this with restrictions on the in types you could have: 但是,如果您准备实施此操作,并且您可以拥有以下类型的限制:

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

return castedList; return castedList;
} }
} }

you can just do this: 你可以这样做:

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

Would love to hear how this could be bad. 很想知道这可能会有什么不好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM