6

How to cast an object (of type Object) into its real type?

I need to do some thing like this

Myobject [i] += Myobject [j];

Myobject's type is Object. Myobject [i] and myobject [j] will always be of same type.

Myobject[i].Gettype() would give me the type... but how would i actually cast the object into that type to perform the '+' operator

Umair Ahmed
  • 11,238
  • 5
  • 33
  • 39

6 Answers6

16

I'm assuming the addition (+) operator is defined for your custom type (MyType in this example).

If so, you simply need to cast the LHS and RHS of the assignment. This is required because both operands must be of known types at compile-time in order to choose the correct operator overload. This is something required by static languages, though dynamic languages (possibly C# 4.0) may resolve this.

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

Update:

Some reflection magic can get around this problem in C# 2.0/3.0 (with lack of dynamic typing).

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 });
}

Note that this only works for non-primitive types. For primitive types such as int, float, etc., you would need to add a switch statement on the type that manually cast the operands and applied the addition operator. This is because operator overloads aren't actually defined for primitive types, but rather built in to the CLR.

Anyway, hope that solves your problem.

Noldorin
  • 144,213
  • 56
  • 264
  • 302
8

Is the type known at compile time?

C# does not (until C# 4.0) support operators on anything except known, fixed types.

You can use operators with generics via a few tricks - like so. Let me know if generics are a factor here (I can talk at length on this...)

In 4.0, you can use:

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

The use of dynamic causes a lot of magic to happen ;-p

Other than those two scenarios, you need to know their type at compile-time, or do a lot of work.

Noldorin
  • 144,213
  • 56
  • 264
  • 302
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Magic is what keeps the world spinning. – Matthew Scharley Jun 23 '09 at 10:54
  • Type would be a numeric type. it could be float, double, integer or any thing – Umair Ahmed Jun 23 '09 at 10:54
  • Which doesn't change anything, unfortunately. The "generics" trick is probably your best bet, but that requires a types array. You could use MakeGenericMethod to switch from `object` to the generic operator code, but it won't be pretty. And MakeGenericMethod is slow (`dynamic` would be better, when released). – Marc Gravell Jun 23 '09 at 10:57
  • 2
    Oh, it can be *done* - it is just a huge amount of work. Not least, "int" and "float" don't actually have operators (they are handled at the IL level) - but "decimal" does. Add the complications of "lifted" operators (Nullable) etc. The best you could do without going mad would be to test for a known finite set of options - float/int/double/decimal etc. But doing an "any type" operation is painful. – Marc Gravell Jun 23 '09 at 11:06
  • @Marc: Indeed, there's no simple and direct way of doing this, but with a bit of type checking it shouldn't be *too* hard. Likely, the OP won't even need to bother about nullable types/lifted operatrs, but that could still be handled without too much hassle. – Noldorin Jun 23 '09 at 11:14
  • Check out my solution. You can compile a function to perform the arithmetic at run-time. Works in VB.Net, probably in C#, too. – Eyal Mar 31 '10 at 14:57
  • Oops, nevermind reading my answer, you know all about this already! – Eyal Mar 31 '10 at 15:19
  • @Eyal - indeed, see the "like so" link. – Marc Gravell Mar 31 '10 at 15:29
  • The link that I liked was this one: http://www.yoda.arachsys.com/csharp/genericoperators.html – Eyal Apr 02 '10 at 14:49
1

If Myobject is an array then

Myobject [i] += Myobject [j];

should work as long as the + operator has been defined for the type.

As Myobject is of type object this will fail with the error:

Operator '+' cannot be applied to operands of type 'object' and 'object'

To get the type at runtime (a contrived example):

double a = 1.0;
double b = 2.0;

object a1 = a;
object b1 = b;

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

ta and tb are set to "Double".

UPDATE:

A word of warning in advance - what I am about to suggest is very ungainly (to say the least)

If you have a finite number of types and are the types guaranteed to be the same. If so you could do the following:

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

and so on.

If the types aren't the same then it's a bit more complicated.

If you have got an unknown number of types then you'll need to wait for C# 4.

Or you could do with reflection as Noldorin suggests.

ChrisF
  • 134,786
  • 31
  • 255
  • 325
0

It is always better to avoid boxing and unboxing and use direct types. I do not know all your background, but maybe it is better to switch array to real type, or use generic list?

MyType[] array = new MyType[x];

or

List<MyType> list = new List<MyType>();
arbiter
  • 9,447
  • 1
  • 32
  • 43
0

I'll suggest using a swicth statement, as the type would be a numeric one. On each branch, you could cast your numbers to temp variables and perform the operation like:

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;
    }
MaLKaV_eS
  • 1,325
  • 3
  • 23
  • 39
0

A better solution for primitive types that doesn't require a switch statement is like this: (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

Solutions for multiply, divide, etc, are similar. Hopefully converting the above to C# won't be too painful! It is important that AddT is shared (static) because recompiling the lambda expression each time will waste clock cycles. Too bad .Net doesn't have a "MyType implements {+,-,*,etc}"!

Eyal
  • 5,728
  • 7
  • 43
  • 70