I thought I'd do a comparison of Martijn's answer and svick's answer...
The following program returns the following results:
Testing with exception: 2430985 ticks
Testing with reflection: 155570 ticks
void Main()
{
var random = new Random(Environment.TickCount);
dynamic test = new Test();
var sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 100000; i++)
{
TestWithException(test, FlipCoin(random));
}
sw.Stop();
Console.WriteLine("Testing with exception: " + sw.ElapsedTicks.ToString() + " ticks");
sw.Restart();
for (int i = 0; i < 100000; i++)
{
TestWithReflection(test, FlipCoin(random));
}
sw.Stop();
Console.WriteLine("Testing with reflection: " + sw.ElapsedTicks.ToString() + " ticks");
}
class Test
{
public bool Exists { get { return true; } }
}
bool FlipCoin(Random random)
{
return random.Next(2) == 0;
}
bool TestWithException(dynamic d, bool useExisting)
{
try
{
bool result = useExisting ? d.Exists : d.DoesntExist;
return true;
}
catch (Exception)
{
return false;
}
}
bool TestWithReflection(dynamic d, bool useExisting)
{
Type type = d.GetType();
return type.GetProperties().Any(p => p.Name.Equals(useExisting ? "Exists" : "DoesntExist"));
}
As a result I'd suggest using reflection. See below.
Responding to bland's comment:
Ratios are reflection:exception
ticks for 100000 iterations:
Fails 1/1: - 1:43 ticks
Fails 1/2: - 1:22 ticks
Fails 1/3: - 1:14 ticks
Fails 1/5: - 1:9 ticks
Fails 1/7: - 1:7 ticks
Fails 1/13: - 1:4 ticks
Fails 1/17: - 1:3 ticks
Fails 1/23: - 1:2 ticks
...
Fails 1/43: - 1:2 ticks
Fails 1/47: - 1:1 ticks
...fair enough - if you expect it to fail with a probability with less than ~1/47, then go for exception.
The above assumes that you're running GetProperties()
each time. You may be able to speed up the process by caching the result of GetProperties()
for each type in a dictionary or similar. This may help if you're checking against the same set of types over and again.