在c#中,我可以将类型对象的变量转换为类型T的变量,其中T在类型变量中定义?
当前回答
下面是一个类型转换和转换的例子:
using System;
public T CastObject<T>(object input) {
return (T) input;
}
public T ConvertObject<T>(object input) {
return (T) Convert.ChangeType(input, typeof(T));
}
编辑:
评论里有人说这个答案没有回答问题。但是T转换。ChangeType(input, typeof(T))提供了解决方案。转换。方法尝试将任何对象转换为作为第二个参数提供的类型。
例如:
Type intType = typeof(Int32);
object value1 = 1000.1;
// Variable value2 is now an int with a value of 1000, the compiler
// knows the exact type, it is safe to use and you will have autocomplete
int value2 = Convert.ChangeType(value1, intType);
// Variable value3 is now an int with a value of 1000, the compiler
// doesn't know the exact type so it will allow you to call any
// property or method on it, but will crash if it doesn't exist
dynamic value3 = Convert.ChangeType(value1, intType);
我用泛型写了答案,因为我认为,当您想要将一个类型转换为另一个类型而不处理实际类型时,这很可能是代码气味的标志。在99.9%的情况下,不需要使用合适的界面。当涉及到反射时,可能有一些边缘情况是有意义的,但我建议避免这些情况。
编辑2:
一些额外的建议:
Try to keep your code as type-safe as possible. If the compiler doesn't know the type, then it can't check if your code is correct and things like autocomplete won't work. Simply said: if you can't predict the type(s) at compile time, then how would the compiler be able to? If the classes that you are working with implement a common interface, you can cast the value to that interface. Otherwise consider creating your own interface and have the classes implement that interface. If you are working with external libraries that you are dynamically importing, then also check for a common interface. Otherwise consider creating small wrapper classes that implement the interface. If you want to make calls on the object, but don't care about the type, then store the value in an object or dynamic variable. Generics can be a great way to create reusable code that applies to a lot of different types, without having to know the exact types involved. If you are stuck then consider a different approach or code refactor. Does your code really have to be that dynamic? Does it have to account for any type there is?
其他回答
public bool TryCast<T>(ref T t, object o)
{
if (
o == null
|| !typeof(T).IsAssignableFrom(o.GetType())
)
return false;
t = (T)o;
return true;
}
你怎么能这么做?您需要一个类型为T的变量或字段,以便在转换后存储对象,但是如果您只在运行时知道T,您如何拥有这样的变量或字段呢?所以,这是不可能的。
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?
下面是我的方法来强制转换一个对象,但不是泛型类型变量,而是一个系统。动态类型:
I create a lambda expression at run-time using System.Linq.Expressions, of type Func<object, object>, that unboxes its input, performs the desired type conversion then gives the result boxed. A new one is needed not only for all types that get casted to, but also for the types that get casted (because of the unboxing step). Creating these expressions is highly time consuming, because of the reflection, the compilation and the dynamic method building that is done under the hood. Luckily once created, the expressions can be invoked repeatedly and without high overhead, so I cache each one.
private static Func<object, object> MakeCastDelegate(Type from, Type to)
{
var p = Expression.Parameter(typeof(object)); //do not inline
return Expression.Lambda<Func<object, object>>(
Expression.Convert(Expression.ConvertChecked(Expression.Convert(p, from), to), typeof(object)),
p).Compile();
}
private static readonly Dictionary<Tuple<Type, Type>, Func<object, object>> CastCache
= new Dictionary<Tuple<Type, Type>, Func<object, object>>();
public static Func<object, object> GetCastDelegate(Type from, Type to)
{
lock (CastCache)
{
var key = new Tuple<Type, Type>(from, to);
Func<object, object> cast_delegate;
if (!CastCache.TryGetValue(key, out cast_delegate))
{
cast_delegate = MakeCastDelegate(from, to);
CastCache.Add(key, cast_delegate);
}
return cast_delegate;
}
}
public static object Cast(Type t, object o)
{
return GetCastDelegate(o.GetType(), t).Invoke(o);
}
请注意,这不是魔术。与dynamic关键字不同,强制转换不会在代码中发生,只会转换对象的底层数据。在编译时,我们仍然需要费力地找出我们的对象可能是什么类型,这使得这个解决方案不切实际。我写这篇文章是为了调用由任意类型定义的转换操作符,但也许有人能找到更好的用例。
其他答案没有提到“动态”类型。因此,要再添加一个答案,您可以使用“动态”类型来存储结果对象,而不必使用静态类型强制转换转换后的对象。
dynamic changedObj = Convert.ChangeType(obj, typeVar);
changedObj.Method();
请记住,使用“动态”,编译器会绕过静态类型检查,如果你不小心,可能会引入运行时错误。
此外,还假定obj是typeVar类型的实例,或者可以转换为该类型。
为了简单起见,将装箱和解装箱放在一边,沿着继承层次结构进行强制转换时不涉及特定的运行时操作。这主要是编译时的事情。本质上,强制转换告诉编译器将变量的值视为另一种类型。
试镜之后你能做什么?你不知道它的类型,所以你不能对它调用任何方法。你不会有什么特别的事情可以做。具体来说,只有当你在编译时知道可能的类型,手动转换它并使用if语句分别处理每个case时,它才有用:
if (type == typeof(int)) {
int x = (int)obj;
DoSomethingWithInt(x);
} else if (type == typeof(string)) {
string s = (string)obj;
DoSomethingWithString(s);
} // ...
推荐文章
- 实体框架核心:在上一个操作完成之前,在此上下文中开始的第二个操作
- 如何为构造函数定制Visual Studio的私有字段生成快捷方式?
- 如何使用JSON确保字符串是有效的JSON。网
- AppSettings从.config文件中获取值
- 通过HttpClient向REST API发布一个空体
- 如何检查IEnumerable是否为空或空?
- 自动化invokerrequired代码模式
- 在c#代码中设置WPF文本框的背景颜色
- 在c#中,什么是单子?
- c#和Java中的泛型有什么不同?和模板在c++ ?
- c#线程安全快速(est)计数器
- 如何将此foreach代码转换为Parallel.ForEach?
- 如何分裂()一个分隔字符串到一个列表<字符串>
- 纬度和经度的数据类型是什么?
- 如何转换列表<字符串>列表<int>?