Switch case on type c#
Update C# 7
Yes: Source
switch(shape)
{
case Circle c:
WriteLine($"circle with radius {c.Radius}");
break;
case Rectangle s when (s.Length == s.Height):
WriteLine($"{s.Length} x {s.Height} square");
break;
case Rectangle r:
WriteLine($"{r.Length} x {r.Height} rectangle");
break;
default:
WriteLine("<unknown shape>");
break;
case null:
throw new ArgumentNullException(nameof(shape));
}
Prior to C# 7
No.
http://blogs.msdn.com/b/peterhal/archive/2005/07/05/435760.aspx
We get a lot of requests for addditions to the C# language and today
I'm going to talk about one of the more common ones - switch on type.
Switch on type looks like a pretty useful and straightforward feature:
Add a switch-like construct which switches on the type of the
expression, rather than the value. This might look something like
this:
switch typeof(e) {
case int: ... break;
case string: ... break;
case double: ... break;
default: ... break;
}
This kind of statement would be extremely useful for adding virtual
method like dispatch over a disjoint type hierarchy, or over a type
hierarchy containing types that you don't own. Seeing an example like
this, you could easily conclude that the feature would be
straightforward and useful. It might even get you thinking "Why don't
those #*&%$ lazy C# language designers just make my life easier and
add this simple, timesaving language feature?"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;
}
Link: https://blogs.msdn.microsoft.com/peterhal/2005/07/05/many-questions-switch-on-type/
c# 7.0: switch on System.Type
The (already linked) new pattern matching feature allows this.
Ordinarily, you'd switch on a value:
switch (this.value) {
case int intValue:
this.value = Math.Max(Math.Min(intValue, Maximum), Minimum);
break;
case decimal decimalValue:
this.value = Math.Max(Math.Min(decimalValue, Maximum), Minimum);
break;
}
But you can use it to switch on a type, if all you have is a type:
switch (type) {
case Type intType when intType == typeof(int):
case Type decimalType when decimalType == typeof(decimal):
this.value = Math.Max(Math.Min(this.value, Maximum), Minimum);
break;
}
Note that this is not what the feature is intended for, it becomes less readable than a traditional if
...else if
...else if
...else
chain, and the traditional chain is what it compiles to anyway. I do not recommend using pattern matching like this.
How to use switch-case on a Type?
You cannot use a switch block to test values of type Type
. Compiling your code should give you an error saying something like:
A switch expression or case label must be a bool, char, string,
integral, enum, or corresponding nullable type
You'll need to use if
-else
statements instead.
Also: typeof(int)
and typeof(Int32)
are equivalent. int
is a keyword and Int32
is the type name.
UPDATE
If you expect that most types will be intrinsic you may improve performance by using a switch block with Type.GetTypeCode(...)
.
For example:
switch (Type.GetTypeCode(type))
{
case TypeCode.Int32:
// It's an int
break;
case TypeCode.String:
// It's a string
break;
// Other type code cases here...
default:
// Fallback to using if-else statements...
if (type == typeof(MyCoolType))
{
// ...
}
else if (type == typeof(MyOtherType))
{
// ...
} // etc...
}
How to check control Type in Switch Case
As of C# 7 you can use type patterns for this:
private void CheckControl(Control ctl)
{
switch (ctl)
{
case TextBox _:
MessageBox.Show("This is My TextBox");
break;
case Label _:
MessageBox.Show("This is My Label");
break;
}
}
Here _
is the syntax for a discard, meaning you don't need to access the value as a TextBox
(or Label
) afterwards.
If you do want to access members of the specific type, you can introduce a pattern variable:
private void CheckControl(Control ctl)
{
switch (ctl)
{
case TextBox textBox:
// Use textBox for any TextBox-specific members here
MessageBox.Show("This is My TextBox");
break;
case Label label:
// Use label for any Label-specific members here
MessageBox.Show("This is My Label");
break;
}
}
Is there a better alternative than this to 'switch on type'?
Switching on types is definitely lacking in C# (UPDATE: in C#7 / VS 2017 switching on types is supported - see Zachary Yates's answer). In order to do this without a large if/else if/else statement, you'll need to work with a different structure. I wrote a blog post awhile back detailing how to build a TypeSwitch structure.
https://learn.microsoft.com/archive/blogs/jaredpar/switching-on-types
Short version: TypeSwitch is designed to prevent redundant casting and give a syntax that is similar to a normal switch/case statement. For example, here is TypeSwitch in action on a standard Windows form event
TypeSwitch.Do(
sender,
TypeSwitch.Case<Button>(() => textBox1.Text = "Hit a Button"),
TypeSwitch.Case<CheckBox>(x => textBox1.Text = "Checkbox is " + x.Checked),
TypeSwitch.Default(() => textBox1.Text = "Not sure what is hovered over"));
The code for TypeSwitch is actually pretty small and can easily be put into your project.
static class TypeSwitch {
public class CaseInfo {
public bool IsDefault { get; set; }
public Type Target { get; set; }
public Action<object> Action { get; set; }
}
public static void Do(object source, params CaseInfo[] cases) {
var type = source.GetType();
foreach (var entry in cases) {
if (entry.IsDefault || entry.Target.IsAssignableFrom(type)) {
entry.Action(source);
break;
}
}
}
public static CaseInfo Case<T>(Action action) {
return new CaseInfo() {
Action = x => action(),
Target = typeof(T)
};
}
public static CaseInfo Case<T>(Action<T> action) {
return new CaseInfo() {
Action = (x) => action((T)x),
Target = typeof(T)
};
}
public static CaseInfo Default(Action action) {
return new CaseInfo() {
Action = x => action(),
IsDefault = true
};
}
}
C# switch on type
See another answer; this feature now exists in C#
I usually use a dictionary of types and delegates.
var @switch = new Dictionary<Type, Action> {
{ typeof(Type1), () => ... },
{ typeof(Type2), () => ... },
{ typeof(Type3), () => ... },
};
@switch[typeof(MyType)]();
It's a little less flexible as you can't fall through cases, continue etc. But I rarely do so anyway.
Using Case/Switch and GetType to determine the object
If I really had to switch
on type of object, I'd use .ToString()
. However, I would avoid it at all costs: IDictionary<Type, int>
will do much better, visitor might be an overkill but otherwise it is still a perfectly fine solution.
C# Case statment string or string
one possiblitiy which should work should be
switch (newButton.fileExtension)
{
case ".txt":
newButton.Image = System.Drawing.Image.FromFile(@"Some Directory\Project Code\Project images\Text document.png");
break;
case ".png":
case ".jpg":
case ".gif":
newButton.Image = System.Drawing.Image.FromFile(@"Some Directory\Project images\Picture document.png");
break;
case ".doc":
newButton.Image = System.Drawing.Image.FromFile(@"Some Directory\Project Code\Project images\Word Document.png");
break;
default:
newButton.Image = System.Drawing.Image.FromFile(@"Some Directory\Project Code\Project images\Unknown Document.png");
break;
}
Related Topics
Create a Coroutine to Fade Out Different Types of Object
What's the Equivalent of Vb's Asc() and Chr() Functions in C#
Replace Parameter in Lambda Expression
Find Out Username(Who) Modified File in C#
In Mvvmcross How to Do Custom Bind Properties
Cannot Access Non-Static Field
How to Draw a Rounded Rectangle as the Border for a Rounded Form
Different Like Behaviour Between My Application and the Access Query Wizard
Differencebetween Manualresetevent and Autoresetevent in .Net
Wrapping Stopwatch Timing with a Delegate or Lambda
How Much Faster Is C++ Than C#
How to Write One to Many Query in Dapper.Net
MVC Web API: No 'Access-Control-Allow-Origin' Header Is Present on the Requested Resource
Setting Unique Constraint with Fluent API
Mvvm in Wpf - How to Alert Viewmodel of Changes in Model... or Should I