如何将对象转换为其类型?

时间:2009-06-23 10:45:47

标签: c#

如何将对象(Object类型)转换为真实类型?

我需要做一些像这样的事情

Myobject [i] += Myobject [j];

Myobject的类型是Object。 Myobject [i]和myobject [j]将永远属于同一类型。

Myobject [i] .Gettype()会给我类型......但是我如何将对象实际转换为该类型以执行'+'运算符

6 个答案:

答案 0 :(得分:16)

我假设为您的自定义类型定义了添加(+)运算符(在此示例中为MyType)。

如果是这样,您只需要投射任务的LHS和RHS。这是必需的,因为两个操作数在编译时必须是已知类型才能选择正确的运算符重载。这是静态语言所需要的,尽管动态语言(可能是C#4.0)可以解决这个问题。

((MyType)Myobject[i]) += (MyType)Myobject[j];

<强>更新

一些反射魔法可以在C#2.0 / 3.0中解决这个问题(缺乏动态类型)。

public static object Add(object a, object b)
{
    var type = a.GetType();
    if (type != b.GetType())
        throw new ArgumentException("Operands are not of the same type.");

    var op = type.GetMethod("op_Addition", BindingFlags.Static | BindingFlags.Public);
    return op.Invoke(null, new object[] { a, b });
}

请注意,这仅适用于非基本类型。对于诸如intfloat等原始类型,您需要在手动转换操作数并应用加法运算符的类型上添加switch语句。这是因为操作符重载实际上并不是为原始类型定义的,而是内置于CLR中。

无论如何,希望能解决你的问题。

答案 1 :(得分:8)

编译时是否知道类型?

除了已知的固定类型之外,C#不支持运营商(直到C#4.0)。

您可以通过一些技巧使用泛型的运算符 - like so。让我知道泛型是否是一个因素(我可以详细谈论......)

在4.0中,您可以使用:

dynamic x = MyObject[i];
x += MyObject[j];
MyObject[i] = x;

使用dynamic会导致很多魔法发生; -p

除了这两种情况之外,你需要在编译时知道它们的类型,或者做很多的工作。

答案 2 :(得分:1)

如果Myobject是一个数组,那么

Myobject [i] += Myobject [j];
只要为类型定义了+运算符,

就会起作用。

由于Myobject属于object类型,因此会失败并显示错误:

  

运算符'+'不能应用于'object'和'object'类型的操作数

要在运行时获取类型(一个人为的例子):

double a = 1.0;
double b = 2.0;

object a1 = a;
object b1 = b;

Type ta = a1.GetType();
Type tb = b1.GetType();

tatb设置为“双倍”。

更新:

提前发出警告 - 我要暗示的是非常笨拙(至少可以说)

如果您的类型数量有限且类型保证相同。如果是这样,您可以执行以下操作:

Type test = Myobject[i].GetType();
if (test.Equals(typeof(double)))
{
   (double)Myobject[i] += (double)Myobject[j];
}

等等。

如果类型不一样,那就有点复杂了。

如果您的类型数量不详,那么您需要等待C#4。

或者你可以用Noldorin建议的反思来做。

答案 3 :(得分:0)

最好避免装箱和拆箱并使用直接类型。我不知道你的所有背景,但也许最好将数组切换到实际类型,或者使用通用列表?

MyType[] array = new MyType[x];

List<MyType> list = new List<MyType>();

答案 4 :(得分:0)

我建议使用switch语句,因为类型是数字类型。在每个分支上,您可以将数字转换为临时变量并执行以下操作:

switch (Myobjetc[j].GetType())
    {
        case typeof(short):                
            break;
        case typeof(int):
            int a, b = 0;
            a = (int)Myobjet[i];
            b = (int)Myobject[j];
            a += b; 
            break;
        case typeof(long):
            break;
        case typeof(decimal):
            break;
        case typeof(double):
            break;
        case typeof(float):
            break;            
        default:
            break;
    }

答案 5 :(得分:0)

对于不需要switch语句的原始类型的更好的解决方案是这样的:(VB.Net)

Private Shared AddT As Func(Of T, T, T)
If AddT = Nothing Then
    Dim paramX As Expressions.ParameterExpression = Expressions.Expression.Parameter(GetType(T), "x")
    Dim paramY As Expressions.ParameterExpression = Expressions.Expression.Parameter(GetType(T), "y")
    Dim body As Expressions.BinaryExpression = Expressions.Expression.AddChecked(paramX, paramY)
    Matrix(Of T).AddT = Expressions.Expression.Lambda(Of Func(Of T, T, T))(body, paramX, paramY).Compile
End If
Private a as MyType
Private b as MyType
AddT(a,b) 'instead of a+b

乘法,除法等的解决方案是类似的。希望将上述内容转换为C#不会太痛苦!重要的是AddT是共享的(静态的),因为每次重新编译lambda表达式都会浪费时钟周期。太糟糕了.Net没有“MyType实现{+, - ,*,etc}”!