2

I was looking for a way to refactor and simplify one function where I have to do data sorting depending on input class type, and got stuck at switch(input.GetType()):

Quick search led me to Why doesn't C# switch statement allow using typeof/GetType()? with a link to http://blogs.msdn.com/peterhal/archive/2005/07/05/435760.aspx

I read the documentation, but I don't get the justification that the situation is confusing.

From the article:

Unfortunately, like many 'simple' language features, type switch is not as simple as it first appears. The troubles start when you look at a more significant, and no less important, example like this:

class C {}
interface I {}
class D : C, I {}

switch typeof(e) {
case C: ... break;
case I: ... break;
default: ... break;
}

What's not simple about it? The call typeof(e) cannot return - this is a I D and C. It has to return a Type not an array of interface and class types - Type[]. So the type of the class D is D. And D corresponds to a default: branch.

An I missing something?

Community
  • 1
  • 1
Coder
  • 3,695
  • 7
  • 27
  • 42
  • see also http://stackoverflow.com/questions/156467/switch-pattern-matching-idea http://stackoverflow.com/questions/7252186/switch-case-on-type-c-sharp http://stackoverflow.com/questions/7542793/how-to-use-switch-case-on-a-type http://stackoverflow.com/questions/4478464/c-sharp-switch-on-type http://stackoverflow.com/questions/298976/c-sharp-is-there-a-better-alternative-than-this-to-switch-on-type – Mikhail Poda May 01 '12 at 11:55
  • and http://stackoverflow.com/questions/94305/what-is-quicker-switch-on-string-or-elseif-on-type http://stackoverflow.com/questions/5947343/how-to-switch-between-possible-type-of-an-object http://stackoverflow.com/questions/10115028/best-way-to-switch-behavior-based-on-type http://stackoverflow.com/questions/2551773/c-sharp-which-is-the-best-alternative-to-switch-on-type – Mikhail Poda May 01 '12 at 11:55

2 Answers2

4

It seems you don't expect the switch to match on subclasses. But this would break the Liskov Substitution Principle. (where if you passed in a C object, the code would work, but not with a D, even though D is a subclass of C).

artbristol
  • 32,010
  • 5
  • 70
  • 103
  • Yes, because we are not branching on class, we are branching on typeof(class) which is a single, well defined value, just like a regular int. You don't branch on value 32 to a different branch if it's defined as (int32)32 or (int64)32. – Coder Jun 10 '11 at 11:10
  • 1
    The principle is a good read though. And I guess someone can break the app by changing class D to it's subclass under some circumstances. – Coder Jun 10 '11 at 11:26
3

I think it's a perfectly valid argument on Peter Hallam's blog post that you don't expect switch statement to differ if you reorder things, so it's really only useful if only one branch can be valid at the same time, whereas with Type one class is always multiple different types along the inheritance chain.

No one stops you from doing this with an if...else chain, where you do expect it to be evaluated in the order you put things.

dain
  • 6,475
  • 1
  • 38
  • 47
  • But it would not differ, because in both cases only default branch would be considered. type is D, it's not a set of types, so there is no way that branch I or C could be executed. You would have to cast the class to C to get branch C. Kind of - ((ClassC)input).GetType(). – Coder Jun 10 '11 at 11:07
  • No, D is also a C and I (and Object), any class is also a valid type of any of its ancestors up on the inheritance chain. – dain Jun 10 '11 at 11:09
  • Of course you could structure your statements that it goes from the higher level / more concrete class definitions to more generic ones, but the point is that this ordering shouldn't be a requirement to do so when working with `switch`, but you can do it with if...else where it's expected that the conditions get evaluated in order and until the first match is found. – dain Jun 10 '11 at 11:12
  • But it's type is D, unless it's cast to a different object. We are not switching on class. Although they can be valid types, you wouldn't expect string a; a.GetType(); to return Object. You would if you'd have performed a cast though. – Coder Jun 10 '11 at 11:15
  • Well `typeof` or `Object.GetType()` returns a `System.Type` which is probably compared on a less strict basis, as in returning true even for inherited types. You could try comparing `Type.FullName` for example if you want it to be stricter. – dain Jun 10 '11 at 11:26