C
C#2y ago
alistairv

❔ Pattern matching on multiple cases with the same-typed members

Hello, I am currently stuck with code like this:
public void Foo(Bar bar) {
if (bar is Bar1 { Prop1: var p1 }) {
// do stuff with p1
} else if (bar is Bar2 { Prop2: var p2}) {
// do the exact same stuff with p2
}
// etc
}
public void Foo(Bar bar) {
if (bar is Bar1 { Prop1: var p1 }) {
// do stuff with p1
} else if (bar is Bar2 { Prop2: var p2}) {
// do the exact same stuff with p2
}
// etc
}
where Bar1 : Bar, Bar2: Bar, ... and the type of Prop1, Prop2, ... is the same. Since Bar is not my type, I cannot simply modify it to suit me better. My question: Is there a way to handle this more elegantly inside the method (aside from extracting a local function)? I am thinking of some syntax like
if (bar is Bar1 { Prop1: var p } or Bar2 { Prop2: p } or ...) {
// do stuff with p
}
if (bar is Bar1 { Prop1: var p } or Bar2 { Prop2: p } or ...) {
// do stuff with p
}
but unfortunately this is invalid syntax. Same holds for
TypeOfProp p = null;
if (bar is Bar1 { Prop1: p } or Bar2 { Prop2: p } or ...) {
// do stuff with p
}
TypeOfProp p = null;
if (bar is Bar1 { Prop1: p } or Bar2 { Prop2: p } or ...) {
// do stuff with p
}
8 Replies
alistairv
alistairvOP2y ago
(context: I am iterating an IOp tree in Roslyn and checking the type of the IOperation of the current node I'm in)
Tinefol
Tinefol2y ago
so the names of the properties are different, but types are the same?
alistairv
alistairvOP2y ago
yes^^
youri
youri2y ago
maybe you could add a custom attribute on the properties that are named different but are functionally the same, then use reflection to identify them and set them
jcotton42
jcotton422y ago
writing the same code a few times is much better than reflection here
HtmlCompiler
HtmlCompiler2y ago
if typeof(Bar1) == typeof(Bar2) then you can use
switch (bar)
{
case Bar1 { Prop1: whatever } baz1: Bar1 foo = baz1; goto catchall;
case Bar2 { Prop2: whatever } baz2: foo = baz2; goto catchall;
catchall:
Console.Write(foo.Prop1);
break;
}
switch (bar)
{
case Bar1 { Prop1: whatever } baz1: Bar1 foo = baz1; goto catchall;
case Bar2 { Prop2: whatever } baz2: foo = baz2; goto catchall;
catchall:
Console.Write(foo.Prop1);
break;
}
but wait maybe you just want to capture Prop? you are not really using it in the condition? turning the matter in another way, why instead can't you
PropType p =
bar is Bar1 foo ? foo.Prop1 :
bar is Bar2 baz ? baz.Prop2 :
throw new UnreachableException() /* or add cases */
;
PropType p =
bar is Bar1 foo ? foo.Prop1 :
bar is Bar2 baz ? baz.Prop2 :
throw new UnreachableException() /* or add cases */
;
alistairv
alistairvOP2y ago
yes, i just want to capture Prop. and the second code snippet is indeed (in my eyes) elegant and readable <a:thumbsup:800164030547230730> similarly to that, in the meantime i thought of ```cs PropType p = bar switch { Bar1 { Prop1: var p1 } => p1, Bar2 { Prop2: var p2 } => p2, => null // or throw... } if (p != null) // do stuff... `` and all of those allow for nested member extraction, like Bar1 { InnerBar.Prop1: var p1 }` which (at least in my IOp tree use-case) is pretty neat
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.

Did you find this page helpful?