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?
Well you have it in your hand. Use
TypeCode
this supports all primitives. for Custom objects Write
else if
statements insideTypeCode.Object
.I hope this helps.
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 toExpression.Equal
, and all the results toExpression.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.