使用Typevariables投射variables

在C#中,我可以将types对象的variables转换为typesT的variables,其中T是在typesvariables中定义的?

当然你可以在这里既简单(假设这是一个T型的演员)演员,如果方便的话(假设我们可以将其转换为T)转换:

 public T CastExamp1<T>(object input) { return (T) input; } public T ConvertExamp1<T>(object input) { return (T) Convert.ChangeType(input, typeof(T)); } 

编辑:

有些人在评论中说这个答案不能回答这个问题。 但是行(T) Convert.ChangeType(input, typeof(T))提供了解决scheme。 Convert.ChangeType方法尝试将任何对象转换为作为第二个参数提供的types。

我已经用generics编写了答案,因为我认为当你想把a something转换a something else而不处理实际的types的时候,这是代码异味的一个很可能的标志。 有适当的接口,这不应该是99.9%的时间。 有些边缘案例在反思时可能有意义,但我build议避免这种情况。

其他答案没有提到“dynamic”types。 因此,要添加一个答案,您可以使用“dynamic”types来存储您的结果对象,而不必使用静态types转换转换的对象。

 dynamic changedObj = Convert.ChangeType(obj, typeVar); changedObj.Method(); 

请记住,使用“dynamic”时,编译器会绕过静态types检查,如果不小心,可能会引入可能的运行时错误。

这是我的方法,不使用generics:

 //using System; //using System.Linq.Expressions; //using System.Reflection; public static object Cast(object obj, Type t) { try { var param = Expression.Parameter(obj.GetType()); return Expression.Lambda(Expression.Convert(param, t), param) .Compile().DynamicInvoke(obj); } catch (TargetInvocationException ex) { throw ex.InnerException; } } 

请注意,这只对数据和底层types执行转换。 返回值仍然是object ,必须用作: dynamic d = Cast(obj, t); ,因为编译器仍然不知道它的实际types。

上面的代码是无法形容的低效率。 每次调用dynamic程序集时,它都会创build一个新的方法。 另一个缺点是它必须知道被铸造物体的types。

我想出了一个更好的方法来完成这个任务,将dynamic创build的方法存储在generics类中,并从存储在字典中的委托中访问它们。 根据我的粗略testing,平均来说,上面的代码需要上百倍,而下面的代码只有经常投入的两倍。 开始:

 //requres a reference to Microsoft.CSharp.dll using Microsoft.CSharp.RuntimeBinder; using System; using System.Collections.Generic; using System.Runtime.CompilerServices; public static class TypeCastHelper { private static Type CastType = typeof(CastClass<>); private static Dictionary<Type, Func<object, object>> Cache = new Dictionary<Type, Func<object, object>>(); private static class CastClass<T> { private static CallSite<Func<CallSite, object, T>> Site; static CastClass() { Site = CallSite<Func<CallSite, object, T>> .Create(Microsoft.CSharp.RuntimeBinder.Binder .Convert(CSharpBinderFlags.ConvertExplicit, typeof(T), CastType)); } public static object Cast(object o) { try { return Site.Target.Invoke(Site, o); } catch (RuntimeBinderException e) { throw new InvalidCastException(e.Message); } } } private static Func<object, object> MakeCastDelegate(Type t) { return (Func<object, object>)CastType.MakeGenericType(t) .GetMethod("Cast") .CreateDelegate(typeof(Func<object, object>)); } public static Func<object, object> GetCastDelegate(Type t) { Func<object, object> d; if (!Cache.TryGetValue(t, out d)) { d = MakeCastDelegate(t); Cache.Add(t, d); } return d; } public static object Cast(object o, Type t) { return GetCastDelegate(t).Invoke(o); } } 

你怎么能这样做? 你需要一个types为T的variables或字段,你可以在转换之后存储对象,但是如果只在运行时才知道T,怎么能有这样的variables或字段呢? 所以,不,这是不可能的。

 Type type = GetSomeType(); Object @object = GetSomeObject(); ??? xyz = @object.CastTo(type); // How would you declare the variable? xyz.??? // What methods, properties, or fields are valid here? 

为简单起见,将装箱和取消装箱放在一边,没有特定的运行时操作涉及inheritance层次结构。 这主要是编译时的事情。 从本质上讲,转换告诉编译器把variables的值作为另一种types。

演员之后你可以做些什么? 你不知道types,所以你不能调用任何方法。 没有什么特别的事情可以做。 具体而言,只有在编译时知道可能的types,手动强制转换以及使用if语句分别处理每个个案时才有用:

 if (type == typeof(int)) { int x = (int)obj; DoSomethingWithInt(x); } else if (type == typeof(string)) { string s = (string)obj; DoSomethingWithString(s); } // ... 
 public bool TryCast<T>(ref T t, object o) { if ( o == null || !typeof(T).IsAssignableFrom(o.GetType()) ) return false; t = (T)o; return true; } 

更清洁:

  public static bool TryCast<T>(ref T t, object o) { if (!(o is T)) { return false; } t = (T)o; return true; }