Click to See Complete Forum and Search --> : casting KeyValuePair<X,Y> into KeyValuePair<Object, Object>?


THY02K
June 21st, 2009, 05:51 AM
hello

I need to cast KeyValuePair<X,Y> into KeyValuePair<Object, Object> ...

Trying to write simpler code... how can I reduce the number of the else-if blocks below?

if (o is DictionaryEntry)
{
DictionaryEntry oEntry = (DictionaryEntry)o;
object oKey = oEntry.Key;
object oValue = oEntry.Value;

// In this case lstAnotherCollection is a Hashtable
lstAnotherCollection.Add(oKey, oValue);
... more ...
}
else if (o is KeyValuePair<string, System.Drawing.Bitmap>)
{
// This would give error ...
// KeyValuePair<object, object> oEntry = (KeyValuePair<object, object>)o;

// To resolve this, I resorted to else-elseif blocks (That's obviously undersirable)
KeyValuePair<string, System.Drawing.Bitmap> oEntry = (KeyValuePair<string, System.Drawing.Bitmap>)o;
string oKey = oEntry.Key;
System.Drawing.Bitmap oValue = oEntry.Value;

// lstAnotherCollection = Dictionary<Object, Object>
lstAnotherCollection.Add(oKey, oValue);
... more ...
}
... many more else-if blocks ...


I suppose I cannot cast KeyValuePair<X,Y> into KeyValuePair<Object, Object> ... because it defeats purpose of Generics in the first place?

Thanks

BigEd781
June 21st, 2009, 05:54 PM
It's hard to give you advice without any context. If I knew what your intention was I could help more, but you are right in thinking that writing code like that is a bad idea. Why would you expect so many different types of objects there?

Arjay
June 21st, 2009, 05:59 PM
Usually when you find yourself having to do this kind of thing, it indicates a poor design.

THY02K
June 21st, 2009, 07:26 PM
yes, this is why I stated I want to eliminate this else if blocks and was looking for a solution - this is code generator code examining obj properties wiring interceptors/fabricating proxy

suggestion?

Arjay
June 21st, 2009, 09:12 PM
Have the KeyValuePair hold onto a base class. See if you can use polymorphism to eliminate the if/else statements.

THY02K
June 21st, 2009, 10:33 PM
yes - i tried casting KeyValuePair<X,Y> into KeyValuePair<Object, Object> (X and Y are Reference Type), no luck... I think I need to think of something...

Arjay
June 22nd, 2009, 10:43 AM
I'm not talking about down to the object level, I'm talking more on the lines of

KeyValuePair< string, MyBaseClass >

If you have too many variations for this, then you might think about changing the way you are receiving the data.

A 'catch-all' kind of approach works okay for very simple things, but doesn't work for slightly more complex things (as you have found out).

We don't have much context for what you are doing, but you mentioned code generation of proxies. Rather than building a proxy that does everything, consider making multiple proxies, specifically one proxy for group of similar types.

THY02K
June 22nd, 2009, 07:19 PM
Thanks... there's got to be a way... probably in arg of called method as supposed to else-if blocks as you've suggested...

BigEd781
June 22nd, 2009, 07:31 PM
No, usually when you find yourself checking the type of an object as a condition it means that you could replace that check with polymorphic behavior. That is what Arjay was saying. For example, (this is simplistic, I know), you may have a base class for Planes:


abstract class Plane
{
abstract void Fly( );
}


All types of planes would inherit from this base class. The Fly( ) method is abstract because, although all planes fly, they do not all do so in the same manner. So, a Cessna would implement the Fly method differently than a Jumbo Jet would, but you would treat them all as instances of the Plane class and simply call the Fly( ) method on each. Each inherited type knows how to fly in their own way, but as a client of the class you don't need to know what that is.


Plane cessna = new Cessna( );
Plane jumbo = new JumboJet( );

censa.Fly( ); // calls Cessna.Fly( )
jumbo.Fly( ); // calls JumboJet.Fly( )


I know that this is overly simplistic, but you can see how this can be very powerful. Instead of checking the type of your object, each type will be encapsulated into a class and they all will share a common interface. Again, if we knew more about your situation we could tell you whether or not this was the right approach.

Phoenix13NL
August 23rd, 2009, 04:47 AM
Would this be an solution for your problem:

lstAnotherCollection.Add(new KeyValuePair<object, object>(o.Key, o.Value));

or

KeyValuePair<object, object> keyValuePair = new KeyValuePair<object, object>(o.Key, o.Value);

?

I dont see any reason why it should be casted, the above should work just fine.

Mutant_Fruit
August 23rd, 2009, 07:15 AM
.NET 4.0 allows this kind of casting via contra-variance and co-variance.