Switch Case on Type C#

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



Leave a reply



Submit