Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: switch on System.Type #8194

Closed
alrz opened this issue Jan 27, 2016 · 16 comments
Closed

Proposal: switch on System.Type #8194

alrz opened this issue Jan 27, 2016 · 16 comments

Comments

@alrz
Copy link
Member

alrz commented Jan 27, 2016

When it comes to runtime type comparison, there are multiple ways to do so, it's more cumbersome if you want to do it multiple times with if else. it would be really nice if we could literally switch on System.Type or System.RuntimeTypeHandle and compiler choose the fastest way, like using TypeHandle.

Type type = ...;
switch(type) {
  case typeof(Foo): ... break;
  case typeof(Bar): ... break;
}
@GeirGrusom
Copy link

It's planned that you can switch on type in C# 7.

I think it will look like this:

switch(baz)
{
    case Foo foo:
        foo.DoFoo();
        break;
    case Bar bar:
        bar.DoBar();
        break;
}

@alrz
Copy link
Member Author

alrz commented Jan 27, 2016

@GeirGrusom That's not what I'm talking about.

@alrz alrz changed the title Proposal: switch on runtime type Proposal: switch on System.Type Jan 27, 2016
@orthoxerox
Copy link
Contributor

Well, it would be nice if types were first-class citizens, but that would require CLR support, I think.

@alrz
Copy link
Member Author

alrz commented Jan 27, 2016

@orthoxerox I even suspect that this behavior can be neatly implemented as an extension is operator (if that would be possible). So, no CLR support is required at all.

@HaloFour
Copy link

The CLR is fully capable of handling the logic. The question is how such a statement should be expanded. I'd imagine it would produce the same IL as a series of if/else statements since the IL switch opcode only works when the values are a range starting at 0 which the runtime type handle would not be.

Type type = obj.GetType();
switch (type)
{
    case typeof(Foo):
        Console.WriteLine("Foo!");
        break;
    case typeof(Bar):
        Console.WriteLine("Foo!");
        break;
    case typeof(Baz):
    default:
        Console.WriteLine("Baz or Something Else!");
        break;
    case typeof(Frob):
        Console.WriteLine("Frob!");
        break;
}

effectively equivalent to:

Type type = obj.GetType();
if (typeof(Foo).IsEquivalentTo(type))
{
    Console.WriteLine("Foo!");
}
else if (typeof(Bar).IsEquivalentTo(type))
{
    Console.WriteLine("Bar!");
}
else if (typeof(Frob).IsEquivalentTo(type))
{
    Console.WriteLine("Frob!");
}
else
{
    Console.WriteLine("Baz or Something Else!");
}

@alrz
Copy link
Member Author

alrz commented Jan 27, 2016

@HaloFour switch with pattern-matching already turns to mix of if, else and switch (at least this is what F# does). So I assume this can be done in a similar way. Also, I don't know about IsEquivalentTo but comparing TypeHandle causes no type load and will be emitted directly to IL (see the link in the opening post).

@HaloFour
Copy link

@alrz In IL it's all conditional branch opcodes, unless the condition meets the incredibly narrow requirements to make it work with switch. I assume that ADTs in F# have an incrementing tag field which do meet those requirements.

If if (typeof(Frob).TypeHandle.Equals(type)) is appreciably more efficient then sure, that's probably what the compiler should emit.

@drewnoakes
Copy link
Member

Should this only match exact types? What about derived types? Would case typeof(object) catch everything or only new object()? Either way it's going to surprise someone somewhere.

@alrz
Copy link
Member Author

alrz commented Jan 28, 2016

@drewnoakes That would be actually nice but then it will depend on the order and we might lose TypeHandle optimization.

@AdamSpeight2008
Copy link
Contributor

Or it'll turn it into a dictionary lookup, similar to VB.net's Select Case

@yume-chan
Copy link

Seems you can do it in future branch
snip_20160410064405
But the compiler will crash when compiling it :(

@alrz
Copy link
Member Author

alrz commented Apr 10, 2016

@CnSimonChan I think that's because switch is already relaxed to accept any expression type (depending on the branch you're on) and this doesn't seem to be something that you'd get it "for free" via pattern-matching. So I think they should make it explicitly an error or consider implementing it.

@gafter
Copy link
Member

gafter commented Apr 11, 2016

@CnSimonChan Reported as #10459

@gafter gafter added the Feature - Pattern Matching Pattern Matching label Apr 11, 2016
@gafter gafter added this to the 2.0 (RC) milestone Apr 11, 2016
@gafter gafter self-assigned this Apr 11, 2016
@gafter
Copy link
Member

gafter commented Apr 11, 2016

Since we have to fix the compiler crash, lets just make this work.

@weitzhandler
Copy link
Contributor

weitzhandler commented Mar 6, 2017

A compelling feature I come a lot across with. I'd love to see this implemented.

@gafter
Copy link
Member

gafter commented Mar 27, 2017

Issue moved to dotnet/csharplang #356 via ZenHub

@gafter gafter closed this as completed Mar 27, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants