say, if I want to intensively test the type of some inherited class, and good performance is desired, should I use enum store all possible types, and use enum equality to test the type instead of using is.
e.g.
switch (myObject.Type)
{
case myType.type1:
myObject as myInheritedObject1;
...
break;
case myType.type2:
myObject as myInheritedObject2;
...
break;
case myType.type3:
myObject as myInheritedObject3;
...
break;
...
}
or
var tmp = myObject as myInheritedObject1;
if (tmp != null)
{
}
else
{
tmp = myObject as myInheritedObject2;
if (tmp != null)
{
}
else
{
tmp = myObject as myInheritedObject3;
if (tmp != null)
{
}
} }}
say, if I want to intensively test the type of some inherited class, and good performance is desired, should I use enum store all possible types, and use enum equality to test the type instead of using
is?
Such a mechanism is usually called a "discriminated type", FYI.
The answer is: it depends on what your performance requirements are. Discriminated types have many drawbacks:
switch that forgets a case and dies horribly at runtime or does something crazy as a result.They have the advantage that they are in fact slightly faster than doing a type test.
So, solve this problem the same way you would solve any other performance problem:
is does not meet your requirements, then evaluate if making the change to discriminated types does cause the program to meet your requirements. If it does, then consider the costs of doing so and make a decision accordingly. If it does not then you have a bigger problem to solve, so solve that problem first.On the Roslyn team we have enormously restrictive performance requirements in every possible way and we therefore considered this question extremely carefully. We decided to go with a general strategy of using discriminated types throughout Roslyn. This means that we have to be extremely careful about the way we design our switches, our type hierarchies, and so on. We also have a dedicated performance team that verifies every day that our performance continues to be on track with customer requirements.
Our requirements are quite different from the vast majority of line-of-business developer's performance requirements; you should not use the Roslyn code as a model for ensuring good performance. Rather, you should use our methodology as a model for ensuring good performance: set goals, measure frequently, and only make architectural changes when doing so actually solves an existing problem.
If you want to intensively test the type of some inherited class, I would use an enum, or as Eric Lippert called it a "Discriminated type". Eric identified 5 drawbacks of this technique, but I disagree with most of the drawbacks. Below I will address each one:
They use much more memory. There is no need for the instances to take up any more memory if the base class defines an abstract property that is defined in the child classes without taking up memory. Below is an example:
abstract class MyBase
{
// Define each child class as a new MyType enum
public abstract MyType Type { get; }
}
class MyChild1 : MyBase
{
public override MyType Type
{
get { return MyType.Child1; }
}
}
EDIT: Adding additional example. Above is an example of not using additional memory. Below additional memory would be used because the "Discriminated type" is saved as a field on the base class instead of being set in code on the child class. If the Type Property is set as abstract and defined in code on the child classes then no additional memory is used.
class MyBase
{
protected MyBase(MyType type) { this.type = type; }
MyType type;
public MyType Type { get { return type; } }
}
class MyChild1 : MyBase
{
public MyChild1() : base(MyType.Child1) { }
}
The information is entirely redundant. This is true, but having the enum and the abstract property will call out to a developer that the child class is a "Discriminated type" and that they need to address other code.
In short, if this type of pattern is really needed, and you have the choice between using the "Discriminated type" pattern and an "AS"/"IS" pattern, I would choose the former because it is faster, easier to read, and more self-documenting.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With