0

for example in c#

void Foo(object obj){
    Do(obj);
}
void Do(T1 obj){}
void Do(T2 obj){}
void Do(T3 obj){}

How can I implement that the Foo function can choose correct Do function to perform obj without using switch or if?

ununion
  • 9
  • 2
  • You can't because the type of `object obj` is unknown at compile time. Use overloading or generic methods instead. To use overloading simply remove `Foo(object obj)`. Why does `Foo(object obj)` exist in the first place? What's the actual problem you want to solve? – Panagiotis Kanavos May 12 '22 at 07:14
  • Check [Member Overloading](https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/member-overloading) in the docs – Panagiotis Kanavos May 12 '22 at 07:17

3 Answers3

0

If you don't want if or switch or cast or pattern matching, you can use dynamic.
Not best practice, likely, but works.

void Foo(object obj){
    dynamic value = obj;
    Do(value); // will throw if obj is not T1 T2 or T3
}
lidqy
  • 1,891
  • 1
  • 9
  • 11
  • [Is the use of dynamic considered a bad practice?](https://stackoverflow.com/questions/31859016/is-the-use-of-dynamic-considered-a-bad-practice) – akop May 12 '22 at 07:32
  • I'd agree dynamic is bad practice here, but it solves the requested demand. – lidqy May 12 '22 at 07:35
  • 1
    I think *in the right circumstances* dynamic is a good fit for this. I'd be happy using it in test code for example, to avoid having to perform more complex checks myself. (It can be particularly useful for calls to generic methods where you know that you've got an `ISomething` but you don't know what `T` is.) I wouldn't generally use it in production code for this, but it's a valid option. – Jon Skeet May 12 '22 at 07:35
  • @lidqy: What do you mean by "here" exactly? We don't know what the context is, which means we don't know whether the downsides of `dynamic` outweigh the upsides. – Jon Skeet May 12 '22 at 07:36
  • @JonSkeet BY "here" I mean the sample he gave with a known small set of possible types (T1, T2, T3) . I'd do it with switch/pattern matching then (or make "Do" a generic method in these Ts or such like). Since these 3 types are likely just sample code, I also agree with you, that in the true use case using dynamic might be a actually a good choice if for example you dont know all possible types, if they came from web service e.g. – lidqy May 12 '22 at 07:41
  • @lidqy: Right, I see what you mean. To be honest, even with just three types, in some code situations I'd consider the simplicity of using `dynamic` to be a better fit than going for pattern matching. I've seen various situations when writing tests, where the simplicity of the tests themselves gets overwhelmed by the "infrastructure" aspects... – Jon Skeet May 12 '22 at 07:55
  • 1
    @JonSkeet Yes can turn out overdosed and overengineered to always put the academical model over the get-things-done and don't-bloat-code approach. 100% or more true for testing situations, anyways... – lidqy May 12 '22 at 08:49
-1

No way. When the type isn't known at compile-time, you have to do runtime-checks and pick the correct method with if/switch.

The only option, to use it without a switch/if is to call Do() directly with correct type.

T1 obj = new T1();

// compiler knows the type and can choose the correct method
yourClass.Do(obj);

Edit

There is a other way with the dynamic "type".

I didn't accept it as solution, because it bypass all the type-safety at compile-time. It can lead to a very unexpected behavior on runtime.

As a example: If you remove one overload Do(T1 obj) and make a call with T1, then you will get an error on runtime (not at compile-time).

T1 obj = new T1();

yourClass.Foo(obj); // <-- this will work at compile-time
// but in runtime, it will end up in a excpetion

// even worse, the compiler is now happy with these bad calls
yourClass.Foo("it accepts a string");
yourClass.Foo(123); // and numbers

And it also introduces a very bad performance.

For more information, look here: Is the use of dynamic considered a bad practice?

akop
  • 5,981
  • 6
  • 24
  • 51
  • 1
    No, this *isn't* the only option. While you clearly don't like `dynamic`, it's definitely an *option* to perform overload resolution at execution time. – Jon Skeet May 12 '22 at 07:34
  • @Jon Skeet: `dynamic` should be avoided. It can lead to very serious problems since it bypass all compiler-checks. More infos here: [SO question](https://stackoverflow.com/questions/31859016/is-the-use-of-dynamic-considered-a-bad-practice). Especially for beginners, it teaches a very bad pattern. Should we show this anti-pattern to beginners? I guess not. – akop May 12 '22 at 07:39
  • No, I believe dynamic should be used *rarely and carefully*. I think there are very few absolutes in terms of "bad practice" - life is a lot more nuanced than that. Rather than have an answer which contradicts itself ("The only option" ... "There is a other way") why not just explain your *preferred* option and say that dynamic would work but you don't recommend it? – Jon Skeet May 12 '22 at 07:57
  • @JonSkeet I added the reasons, why it should not be used. – akop May 12 '22 at 08:03
  • Yes, but your answer still contradicts itself... and I'm saying I disagree with an absolutist approach to this. There are definitely downsides to dynamic that it's good to make people aware of - but this "it's bad practice, don't use it" with an implied "ever, ever, ever" does no-one any favours IMO. – Jon Skeet May 12 '22 at 08:37
  • Yeah, I'm a hardliner about the `dynamic`-keyword. I saw a lot of beginners, which found `dynamic` and using it more and more. They starting to forget the annoying type-safety at all. So, I'll still say "don't use the black magic" and I'll never show it as solution. – akop May 12 '22 at 08:53
  • But I think, that we can agree, that we didn't agree. :) I will leave my answer as it is. – akop May 12 '22 at 08:55
-1

AFAIK, you need to specify what the type is so that the correct Do() can be called. Maybe something like (I have no idea if this would work tho)

Do((obj as T1)?? (obj as T2)?? (obj as T3));