In many cases we may want to extract a list of concrete object types from a list with more abstract types. For example if we have a List of users, we may want to extract another list of users which are administrators (let’s suppose administrator inherits user). I did some very basic tests to check which approach will be faster to achieve this (by faster I mean optimized, not faster to write). I used a List |
Candidate 2 : Iterate the collection with foreach, get each element as object and check it with “is” operator against int type.
Candiate 3 : Use OfType with ToList, which is only one line of code.
Let’s see the classes (I did a separate class for each approach)
class ISSample
{
public static void StartSample(List<object> objects)
{
int processed = 0;
List<int> intList = new List<int>();
long ticksStart = DateTime.Now.Ticks;
foreach (object obj in objects)
{
processed++;
if (obj is int)
{
intList.Add((int)obj);
}
}
long ticksEnd = DateTime.Now.Ticks;
double result = Convert.ToDouble(ticksEnd - ticksStart) / TimeSpan.TicksPerSecond;
Console.WriteLine("IS executed for : " + result.ToString("N10")
+" seconds, items processed: " + processed);
}
}
class ASOperatorSample
{
public static void StartSample(List<object> objects)
{
int processed = 0;
List<int> intList = new List<int>();
long ticksStart = DateTime.Now.Ticks;
foreach (object obj in objects)
{
processed++;
int? obj2 = obj as int?;
if (obj2 != null)
{
intList.Add((int)obj2);
}
}
long ticksEnd = DateTime.Now.Ticks;
double result = Convert.ToDouble(ticksEnd - ticksStart) / TimeSpan.TicksPerSecond;
Console.WriteLine("AS executed for : " + result.ToString("N10") + " seconds items processed: " + processed.ToString());
}
}
class OfTypeSample
{
public static void StartSample(List<object> objects)
{
List<int> intList = new List<int>();
long ticksStart = DateTime.Now.Ticks;
// Here is how this is done in C# 3.5 style
// with one line only
intList = objects.OfType<int>().ToList<int>();
long ticksEnd = DateTime.Now.Ticks;
double result = Convert.ToDouble(ticksEnd - ticksStart) / TimeSpan.TicksPerSecond;
Console.WriteLine("OfType executed for : " + result.ToString("N10") + " seconds.");
}
}
Now let’s see some outputs:
AS executed for : 5.3281250000 seconds items processed: 10000000
IS executed for : 0.3750000000 seconds, items processed: 10000000
OfType executed for : 0.7812500000 seconds.
Press any key to continue . . .
AS executed for : 5.6562500000 seconds items processed: 10000000
OfType executed for : 0.7812500000 seconds.
IS executed for : 0.5312500000 seconds, items processed: 10000000
Press any key to continue . . .
OfType executed for : 0.9375000000 seconds.
AS executed for : 5.5468750000 seconds items processed: 10000000
IS executed for : 0.3906250000 seconds, items processed: 10000000
Press any key to continue . . .
As you can see there is slight difference in the results depending on which approach will we call first. The obvious thing is that Is operator is always faster, followed by the OfType and the last place is for AS operator.
You may note that for the “is” and “as” operators I added “items processed:” portion. This is very important - by using foreach you can do some statistics inside the loop, while using OfType won’t let you write any code inside the loop.
1 comment:
Узнал много. Спасибо
Post a Comment