Reputation: 595
Instead of overloading a function 100 times or creating 100 different Comparers for different types I've decided to check the type within one function.
For example I'm using a default comparer to compare values of a set of types (primitives and strings) within 2 objects. It contains the following code:
public class DefComparer : IComparer<object> {
public int Compare(object a, object b) {
.... // a = a.GetType().GetField(field).GetValue(a); - not important for the question but I'm just showing that a&b below are different references
switch (a.GetType().Name) {
case "Byte":
if ((byte)a == (byte)b) return 0;
else if ((byte)a > (byte)b) return 1;
else return -1;
case "UInt16":
if ((ushort)a == (ushort)b) return 0;
else if ((ushort)a > (ushort)b) return 1;
else return -1;
case "SByte":
if ((sbyte)a == (sbyte)b) return 0;
else if ((sbyte)a > (sbyte)b) return 1;
else return -1;
case "Int16":
...
Here I'm using a switch
statement that is said to be faster than a chain of if
/else
statements. But a.GetType().Name
returns a string that is dynamically obtained and this method involves string comparisons. That doesn't sound particularly fast to me. I need the Comparer to be as fast as technically possible because It's going to be used on large collections of data.
Q: Is there a faster way to check the type of an object (that does not involve string comparisons)? What is the fastest possible way?
Upvotes: 8
Views: 4008
Reputation: 283793
From the comments, it sounds as if you have a bunch of structured data, with subobjects of varying type.
If the collections are large, the fastest way will be dynamic codegen (with expression trees perhaps) to create a single method that pulls all the fields/properties of interest out in a strongly typed way, and performs strongly typed comparisons.
Basically, you use reflection to get the field/property types dynamically from the collection member type. Then you build MemberAccessExpression
expressions, pass those to Expression.Equal
, and all the results to Expression.AndAlso
. Compiling the expression gives you a delegate that takes two objects of the particular type contained in the collection.
Startup time will be a couple orders of magnitude slower than the code you showed in your question, but the cost per-object will be a whole lot lower. You'll have to test to see where the breakeven point is -- but probably in the low thousands.
Upvotes: 3
Reputation: 73502
Well you have it in your hand. Use TypeCode
int a = 10;
Type t = a.GetType();
switch (Type.GetTypeCode(t))
{
case TypeCode.Boolean:
break;
case TypeCode.Byte:
break;
case TypeCode.Char:
break;
case TypeCode.DBNull:
break;
case TypeCode.DateTime:
break;
case TypeCode.Decimal:
break;
case TypeCode.Double:
break;
case TypeCode.Empty:
break;
case TypeCode.Int16:
break;
case TypeCode.Int32:
break;
case TypeCode.Int64:
break;
case TypeCode.Object:
break;
case TypeCode.SByte:
break;
case TypeCode.Single:
break;
case TypeCode.String:
break;
case TypeCode.UInt16:
break;
case TypeCode.UInt32:
break;
case TypeCode.UInt64:
break;
default:
break;
}
this supports all primitives. for Custom objects Write else if
statements inside TypeCode.Object
.
I hope this helps.
Upvotes: 11