Replies: 21 comments 36 replies
-
I just ran into this and was really surprised that, given c#7's new switch statement stuff, that this simple case was still not covered. there is a rather long-winded workaround, however: Type type = ...;
switch(type) {
case Type t when t == typeof(Foo): ... break;
case Type t when t == typeof(Bar): ... break;
} |
Beta Was this translation helpful? Give feedback.
-
Do you think this could be championed? You indicated above that you thought it was worth doing, and I think it fits nicely in with pattern matching. I would be happy to implement it. |
Beta Was this translation helpful? Give feedback.
-
@YairHalberstadt I am not interested in championing this. |
Beta Was this translation helpful? Give feedback.
-
Understood. That's a pity. It's only a minor feature, but it comes up quite regularly. For example you suggested I use it in dotnet/roslyn#32843 (comment) EDIT: I was talking nonsense. You didn't suggest that. You suggested something else that didn't compile for a different reason. |
Beta Was this translation helpful? Give feedback.
-
That was not what I meant by "switching on the type". I meant something like switch (someObject)
{
case SomeType1 s1:
....
case SomeType1 s2:
...
case SomeType3 s3:
...
} I'm working on our options for making this compile reliably to a constant-time dispatch in future versions (likely C# 9 or so) without any source changes. |
Beta Was this translation helpful? Give feedback.
-
My TypeConverters will look so much better when this is implemented! |
Beta Was this translation helpful? Give feedback.
-
I do this more operation far more than I do any other scenario where a switch statement/expression would be useful. And I always have to use |
Beta Was this translation helpful? Give feedback.
-
Following - also interested in this feature. |
Beta Was this translation helpful? Give feedback.
-
Just hit this doing some stuff with custom model binding in ASP.NET; I have a value which is |
Beta Was this translation helpful? Give feedback.
-
I've come across scenarios where this can be used as an acceptable replacement if you know the type in question is a struct. e.g. public string M<T>() where T:struct => default(T) switch {
byte => "byte",
sbyte => "sbyte"
_ => "Not a byte or sbyte"
}; Unfortunately, doesn't really work when all you have is a type and you want to switch as ref types default is null. |
Beta Was this translation helpful? Give feedback.
-
This is a feature I have been waiting for as I use this exact pattern in my current project. I prefer switch statements to else if chains because they very clearly communicate their purpose (whereas an else if chain can be ambiguous at times). Seeing how they both compile into basically the same thing, I can't imagine this functionality being too hard to add in. |
Beta Was this translation helpful? Give feedback.
-
FYI- I just noticed Github Discussions doesn't seem to have a way to sort by "Thumbs Up" of the original post - you have to separately up vote the issue itself up. So to keep visibility on this issue - I suggest that all the people asking for it do that in addition to the thumbs up. |
Beta Was this translation helpful? Give feedback.
-
You can do it now but with a slightly different syntax: using System;
Type type = ...;
switch(type) {
case var x when x == typeof(int):
break;
case var x when x == typeof(string):
break;
} In my eyes this is sufficent. And it works for switch expressions, too: var typename = GetValue()?.GetType() switch
{
var type when type == typeof(int) => "int",
var type when type == typeof(string) => "string",
_ => throw new NotSupportedException()
}; In CSharp 8 we introduced the "Constant-Pattern". Perhaps you could propose a "Non-Constant-Pattern" with a link to this discussion.
|
Beta Was this translation helpful? Give feedback.
-
Does the suggestion also take into account code elision? Currently in generic methods checks against a typeof() is completely elided if possible. The switch with the type should also take this into account. |
Beta Was this translation helpful? Give feedback.
-
This issue was linked to from here: https://www.reddit.com/r/csharp/comments/q5zsbr/switcht The requested example:
This would be great syntactic sugar for the following best answer in that thread:
This doesn't look to difficult to implement, the meaning is clear and it is narrow in scope (just the switch statement). |
Beta Was this translation helpful? Give feedback.
-
I was facing this use case today as well and created #5687 but was directed to this discussion. private int ToInt() => _value switch {
int i => i,
long l => (int)l,
_ => default
}
private int ToLong() => _value switch {
int i => i,
long l => l,
_ => default
}
public T As<T>()
{
T x = default;
return x switch
{
int when ToInt() is T i => i,
long when ToLong() is T l => l,
_ => default
}
} But I'm more concerned about performance. Thinking outside the boxMaybe instead of having one generic method with a switch, we could have multiple methods? public int As<T>() where T is int
{ ... }
public long As<T>() where T is long
{ ... } |
Beta Was this translation helpful? Give feedback.
-
So it seems the above hasn't got any solution still - I ran into this when working on creating a custom DataContractResolver - sadly public override bool TryResolveType(Type type, Type? declaredType, DataContractResolver knownTypeResolver, out XmlDictionaryString? typeName, out XmlDictionaryString? typeNamespace)
{
return (type, declaredType) switch
{
(DateOnly, DateOnly) => resolveTypeToXML(typeof(DateOnly), out typeName, out typeNamespace),
_ => knownTypeResolver.TryResolveType(type, declaredType, knownTypeResolver, out typeName, out typeNamespace)
};
} Gives me the error |
Beta Was this translation helpful? Give feedback.
-
Maybe we should first turn switch statement to F# switch statement, then in that prototype add support for switch to do type checking like we can in F#, and release them together under a new brand called the new switch |
Beta Was this translation helpful? Give feedback.
-
I also need this feature. One key aspect to remember here is that most of the code is already done for strings, so allowing types is literally just lifting a restriction. (Granted, adding typeof() to cases may be extra work. ) |
Beta Was this translation helpful? Give feedback.
-
This issue and many adjacent ones could be solved if |
Beta Was this translation helpful? Give feedback.
-
Just out of curiosity, |
Beta Was this translation helpful? Give feedback.
-
@alrz commented on Tue Jan 26 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 literallyswitch
onSystem.Type
orSystem.RuntimeTypeHandle
and compiler choose the fastest way, like usingTypeHandle
.@GeirGrusom commented on Tue Jan 26 2016
It's planned that you can switch on type in C# 7.
I think it will look like this:
@alrz commented on Wed Jan 27 2016
@GeirGrusom That's not what I'm talking about.
@orthoxerox commented on Wed Jan 27 2016
Well, it would be nice if types were first-class citizens, but that would require CLR support, I think.
@alrz commented on Wed 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 commented on Wed Jan 27 2016
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 ILswitch
opcode only works when the values are a range starting at 0 which the runtime type handle would not be.effectively equivalent to:
@alrz commented on Wed Jan 27 2016
@HaloFour
switch
with pattern-matching already turns to mix ofif
,else
andswitch
(at least this is what F# does). So I assume this can be done in a similar way. Also, I don't know aboutIsEquivalentTo
but comparingTypeHandle
causes no type load and will be emitted directly to IL (see the link in the opening post).@HaloFour commented on Wed Jan 27 2016
@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 commented on Thu Jan 28 2016
Should this only match exact types? What about derived types? Would
case typeof(object)
catch everything or onlynew object()
? Either way it's going to surprise someone somewhere.@alrz commented on Thu Jan 28 2016
@drewnoakes That would be actually nice but then it will depend on the order and we might lose
TypeHandle
optimization.@AdamSpeight2008 commented on Thu Jan 28 2016
Or it'll turn it into a dictionary lookup, similar to VB.net's
Select Case
@CnSimonChan commented on Sat Apr 09 2016
Seems you can do it in future branch

But the compiler will crash when compiling it :(
@alrz commented on Sat Apr 09 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 commented on Mon Apr 11 2016
@CnSimonChan Reported as #10459
@gafter commented on Mon Apr 11 2016
Since we have to fix the compiler crash, lets just make this work.
@weitzhandler commented on Mon Mar 06 2017
A compelling feature I come a lot across with. I'd love to see this implemented.
Beta Was this translation helpful? Give feedback.
All reactions