3

C#, Is it possible to recast an object and access methods and properties without creating new object variable?

For example:

foreach (object o in collection)
{
    if (o is MyType)
        {
            (MyType)o.MyProperty = x
        }
 }

Currently, I have to re-cast o to another variable of MyType [ex: MyType m = (MyType)o ] in order to access methods or properties of MyType. It seems wasteful, so I'm wondering if I'm missing some mechanic that will allow me to skip the declaration of a new object variable.

Steve
  • 213,761
  • 22
  • 232
  • 286
Jake Shakesworth
  • 3,335
  • 4
  • 29
  • 43
  • I don't understand what you mean by "wasteful". It's not like the compiler does something special because you declare a local variable that it would not do if you merely said `((MyType)o).MyProperty`. Also, `is` and cast is frowned upon. Use `as` instead and check for nullity: http://stackoverflow.com/questions/2139798/why-is-the-c-sharp-as-operator-so-popular/2139818#2139818 – Mehrdad Afshari Aug 26 '12 at 16:57
  • Why do you consider it wasteful? Do you mean it's overly verbose? – CodesInChaos Aug 26 '12 at 16:58

5 Answers5

4

Your code doesn't work because . has higher precedence than the cast. So you need to add parentheses:

foreach (object o in collection) 
{ 
    if (o is MyType) 
        { 
            ((MyType)o).MyProperty = x; 
        } 
 } 
CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
Steve
  • 213,761
  • 22
  • 232
  • 286
3

You can use Linq:

foreach(MyType t in collection.OfType<MyType>()) {}

You can also use direct casting:

foreach(object o in collection)
{
    if(o is MyType)
    {
        ((MyType)o).MyProperty = x;
    }
}

Alternatively if you you know or want to make sure (keep in mind an InvalidCastException would be possible if the collection is mixed types), you can use the Cast Linq method:

// If your collection is all of the same type
foreach(MyType t in collection.Cast<MyType>()) {}
Christopher Currens
  • 29,917
  • 5
  • 57
  • 77
  • 1
    You'd be wanting `OfType` here, not `Cast`, to prevent an `InvalidCastException`. – Mehrdad Afshari Aug 26 '12 at 16:55
  • @ChristopherCurrens The OP's code fits `OfType`, not `Cast` since he's checking if the type fits with `is`. – CodesInChaos Aug 26 '12 at 16:59
  • @Christopher I know, but the OP is explicitly checking for `if (x is T)` which implies that the collection might contain other elements as well, which makes `Cast` choke. – Mehrdad Afshari Aug 26 '12 at 17:00
  • Thank you, yes the collection is of mixed types and I'm trying to avoid InvalidCastExceptions. And, by "wasteful" I simply meant that it's an extra line of code that may not be necessary. Thanks for the responses. – Jake Shakesworth Aug 26 '12 at 17:06
2

You need two pairs of parentheses.

((MyType)o).MyProperty = x;

Otherwise the casting is applied to the whole expression.


y = (MyType)o.MyMethod(x);

is the same as

y = (MyType)(o.MyMethod(x));

which is not what you want (it casts the result of MyMethod). Instead write

y = ((MyType)o).MyMethod(x);
Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
0

Yes you can cast

foreach(var t in collection.Cast<YourType>())
{
  t.MyProperty = x;
}

Nota : but you must know that boxing or unboxing operation are expensive operation in your memory, when you pass from reference type to value type , or value type to reference type.

In this case you don't have this constraints.

Aghilas Yakoub
  • 28,516
  • 5
  • 46
  • 51
0

implement an Interface

interface MyInterface
{
 string MyProperty;
}

foreach(object o in collection)
{
MyInterface o= originalObject as MyInterface

if (MyInterface!= null)

  ((MyInterface)o).MyProperty = x;
}
Hassan Boutougha
  • 3,871
  • 1
  • 17
  • 17