Possible Duplicate:
Is there a better alternative than this to 'switch on type'?
I need to iterate through all properties of my class and to check if its type of int the i need to do something, if its string .. then do something. I need it using switch-case. Here i am using switch in the following manner, but it asks for some constant. see the code below:
public static bool ValidateProperties(object o)
{
if(o !=null)
{
var sourceType = o.GetType();
var properties = sourceType.GetProperties(BindingFlags.Public | BindingFlags.Static);
foreach (var property in properties)
{
var type = property.GetType();
switch (type)
{
*case typeof(int):* getting error here
// d
}
}
}
}
Also i want to know , what check should I use, typeof(int) or typeof(Int32)?
You cannot use a switch block to test values of type Type
. Compiling your code should give you an error saying something like:
A switch expression or case label must be a bool, char, string, integral, enum, or corresponding nullable type
You'll need to use if
-else
statements instead.
Also: typeof(int)
and typeof(Int32)
are equivalent. int
is a keyword and Int32
is the type name.
UPDATE
If you expect that most types will be intrinsic you may improve performance by using a switch block with Type.GetTypeCode(...)
.
For example:
switch (Type.GetTypeCode(type))
{
case TypeCode.Int32:
// It's an int
break;
case TypeCode.String:
// It's a string
break;
// Other type code cases here...
default:
// Fallback to using if-else statements...
if (type == typeof(MyCoolType))
{
// ...
}
else if (type == typeof(MyOtherType))
{
// ...
} // etc...
}
A good and extensible way to do this is to make a dictionary of types and delegates of appropriate type, based on what you want to do with values of that type.
For example:
var typeProcessorMap = new Dictionary<Type, Delegate>
{
{ typeof(int), new Action<int>(i => { /* do something with i */ }) },
{ typeof(string), new Action<string>(s => { /* do something with s */ }) },
};
And then:
void ValidateProperties(object o)
{
var t = o.GetType();
typeProcessorMap[t].DynamicInvoke(o); // invoke appropriate delegate
}
This solution is extensible, configurable even at run time, and as long as you keep the keys and types of delegate values in typeProcessorMap
correctly matched is also type safe.
See it in action.
Usually, the easiest solution is to switch on the type name:
switch (type.Name)
{
case "Int32":
...
}
This "answer" is an elaboration for Jon's answer. (Marking CW)
For the record, DynamicInvoke
is a bit slow. To illustrate this, consider the following program:
void Main()
{
Func<int, string> myFunc = i => i.ToString();
myFunc.DynamicInvoke(1); // Invoke once so initial run costs are not considered
myFunc(1);
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < 1000000; i++)
myFunc.DynamicInvoke(1);
stopwatch.Stop();
var elapsed = stopwatch.Elapsed;
stopwatch.Restart();
for (int i = 0; i < 1000000; i++)
myFunc(1);
stopwatch.Stop();
var elapsed2 = stopwatch.Elapsed;
Console.WriteLine("DynamicInvoke: " + elapsed);
Console.WriteLine("Direct Invocation: " + elapsed2);
}
Prints out:
DynamicInvoke: 00:00:03.1959900
Direct Invocation: 00:00:00.0735220
Which means that DynamicInvoke
(in this simple case) is 42 times slower than direct invocation.
精彩评论