Click here to Skip to main content
13,149,756 members (82,292 online)
Rate this:
Please Sign up or sign in to vote.
See more:
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 8:05am
Mehdi Gholam344.1K
Naerling 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 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 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 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 23-Nov-11 14:48pm
Did you see my article (please see my solution)? More or less similar.
SAKryukov 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 23-Nov-11 15:05pm
Dictionary Type, Action of ? won't compile
Paulo Zemek 23-Nov-11 16:46pm
I just corrected that and than saw your comment... it is Action<object>
Mehdi Gholam 24-Nov-11 1:08am
So in the MethodToDealWithInt32 method you would do a cast right?
Paulo Zemek 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 :)
Mehdi Gholam 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 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 23-Nov-11 14:53pm
Bookmarked for future reading :)
SAKryukov 23-Nov-11 21:25pm
Thank you, Naerling.
Mehdi Gholam 23-Nov-11 15:11pm
I'm digesting your article, let you know soon.
SAKryukov 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
Top Experts
Last 24hrsThis month

Advertise | Privacy |
Web04 | 2.8.170924.2 | Last Updated 23 Sep 2014
Copyright © CodeProject, 1999-2017
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