Click here to Skip to main content
Rate this: bad
Please Sign up or sign in to vote.
See more: C#
Say we have the following :
object[] objs = new object[3]{ "the ultimate question", 42L, 1}; 
and we want to do something to the individual objects in the array like :
foreach (object o in objs)
Now dosomething will only take object parameters so there is boxing going on, but we require to be able to do something based on the type of the object, so we would do something like :
public void dosomething(object obj)
   // one way
   if(obj.GetType() == typeof(string))
      // string specific something
   // another way
   if(obj is long)
      // long specific something
Well it's ugly and non performant, is there a better way possible using generics etc.?
Posted 23-Nov-11 9:05am
Mehdi Gholam259.2K
Naerling at 23-Nov-11 14:36pm
Good question. I've come along such cases a couple of times where it was necessary to have a huge switch statement to test for type.
Only for work with third party tools by the way ;)
Philippe Mori at 23-Sep-14 21:06pm
Do you have to use object or you can use your own base class?
Does the dispacthing based on type is done at a single location or you have to do it over and over again?
Visitor pattern might be interesting in that case.
Mehdi Gholam at 24-Sep-14 16:07pm
Generally it's object.
Again generally the dispatch is done from one place, say a tcp handler which may accept different types of messages which have to routed to their respective handlers (handlers which can be dynamically registered).
Rate this: bad
Please Sign up or sign in to vote.

Solution 1

First, as your array is already typed as object, the boxing occurs when building the array. Reading the values from the array does not do a new boxing (it can unbox it).
To test for types, it is better to use the is operator. Never compare using GetType() or GetType().Name/FullName.
But then, it is all related to the purpose.
Why are you putting all the values in an array?
If you need them in an array or list, like a generic data to be viewed by the appropriate viewer (similar to Data-Templates) then you can't avoid boxing.
If you want something to deal with datatypes and that can be configurable, you can create a Dictionary. Something like:
var dictionary = new Dictionary<Type, Action<object>>();
// Then you register all the types you want like:
dictionary.Add(typeof(int), MethodToDealWithInt32);
dictionary.Add(typeof(string), MethodToDealWithString);
//Then, when you get a value, you call it like:
public void Call(object value)
  if (value == null)
  Action<object> action = dictionary[value.GetType()];
  // this will thrown an exception if there is no action registered for the type.
With that, you can register the appropriate action for any new type. Surely you will need to do that at some time in your application, but then the caller of "Call()" does not need to have any strong reference to the code that effectively deals with the object.
Naerling at 23-Nov-11 14:32pm
Nice solution! I was thinking more of an Interface that has an Object and a DoSomething method (see my answer).
Yours seems like less work, and it's still an elegant solution.
My 5! :)
SAKryukov at 23-Nov-11 14:48pm
Did you see my article (please see my solution)? More or less similar.
SAKryukov at 23-Nov-11 14:50pm
My 5. I have a solution based on more or less similar idea, perhaps more comprehensive. Please see my article referenced in my solution.
Mehdi Gholam at 23-Nov-11 15:05pm
Dictionary Type, Action of ? won't compile
Paulo Zemek at 23-Nov-11 16:46pm
I just corrected that and than saw your comment... it is Action<object>
Mehdi Gholam at 24-Nov-11 1:08am
So in the MethodToDealWithInt32 method you would do a cast right?
Paulo Zemek at 24-Nov-11 7:12am
Right. In that case, it will be unboxing the value, which is fast. The problem is boxing (which allocates memory) but this happens only when storing a value type as object (like when putting it into the array).
Rate this: bad
Please Sign up or sign in to vote.

Solution 2

Depends on what you want. Using Objects to store just about anything looks like a bad idea anyway.
If you'd work with Generics you'd have something like List<Object> which yields the same result.
What you have there seems like a 'God Method[^]' that can do all sorts of different things dependent on its input.
One way perhaps is to have an Interface that has a Property Object and a Method DoSomething. That way you could write a Class and a specific DoSomething for each type.
I imagine an implementation would look something like this:
public interface IDoSomethingWithObj
    object TheObject { get; set; }
    void DoSomething();
public class DoSomethingWithString : IDoSomethingWithObj
    object IDoSomething.TheObject { get; set; } // Test if the object is a string here, otherwise throw an Exception.
    String MyString { get; set; } // Set TheObject here. Sort of 'fakes' type safety.
    void DoSomething() { // Do something with the String. }
Also, possibly set the String in the Constructor (MyString isn't available in the Interface).
Now you could have a list or array of IDoSomethingWithObj.
foreach (IDoSomethingWithObj obj in myList)
{ obj.DoSomething }
I guess this is one way of handling such a situation (may not be the best, but better than having to make huge switch statements I guess).
The downside is that you cannot replace the Objects with other Objects (if you wanted to) because this is more or less 'type safe' so you'd have to make sure the new Objects type matched the old.
Another Method, if you know what you want (like always a String, int, long, bool in that order) you could use a Tuple[^].
The downside here is that you have no idea what Properties like 'Item1' up to 'Item8' could possible mean.
Nice question. Interested in other solutions too Smile | :)
Mehdi Gholam at 23-Nov-11 15:09pm
Tuple is interesting but is limited to a maximum of 8 items ( I need this for RaptorDB datarows which can easily be more than 8 columns).
Naerling at 23-Nov-11 15:18pm
If that's your case my solution won't work anyway. It requires you to know your types at design time :)
Can't help you with RaptorDB, I only know the relational model ;)
Rate this: bad
Please Sign up or sign in to vote.

Solution 3

I offer a comprehensive solution in my article "Dynamic Method Dispatcher, No more long switch statements!".
Naerling at 23-Nov-11 14:53pm
Bookmarked for future reading :)
SAKryukov at 23-Nov-11 21:25pm
Thank you, Naerling.
Mehdi Gholam at 23-Nov-11 15:11pm
I'm digesting your article, let you know soon.
SAKryukov at 23-Nov-11 21:25pm
Bon appetite!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 /\jmot 230
1 Zoltán Zörgő 210
2 Peter Leow 145
3 Sergey Alexandrovich Kryukov 115
4 _Asif_ 108
0 Sergey Alexandrovich Kryukov 9,353
1 OriginalGriff 6,881
2 Peter Leow 4,577
3 Zoltán Zörgő 4,129
4 Richard MacCutchan 2,882

Advertise | Privacy | Mobile
Web04 | 2.8.150129.1 | Last Updated 23 Sep 2014
Copyright © CodeProject, 1999-2015
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100