0

Using this simple example where :

    void SomeMethod(int varA, string varB) {}
    void SomeMethod(List<int> varA, string varB) {}
    void SomeMethod(int varA, List<string> varB) {}
    void SomeMethod(List<int> varA, List<string> varB) {}

this would grow in n*n and i feel there must be a better way. one of my ideas would be to make it generic as in the following

    void SomeMethod<T1,T2>(T1 varA, T2 varB) 
         where T1 in { int, List<int> }
         where T2 in { string, List<string> }
    {
        if(varA is int intA)
            //do int actions
        else 
            //do List<int> actions
        //...
    }

I have found this one similar question (C# generics - Can I make T be from one of two choices?), but the answers there don't apply here

Any ideas ?

EDIT: I am simplifying here for simplicity sake, the objective would be to check if the param is a value or a collection of values, and if it is a simple value, turn into a collection with a single value and pass it to another overload that takes a collection, @charlieface in the comments has the idea, but it will take multiple params, in which each can be simple value T or a collection of T.

A js working example of what i pretend to achieve in c# below

    var nonArrayToArray = (someValue) => Array.isArray(someValue) ? 
    someValue : [someValue];
    var doSomething = (valueCanBeListOnObject, valueCanBeListOnObject2, 
    valueCanBeListOnObject3) => {
      const guaranteedList = nonArrayToArray(valueCanBeListOnObject);
      const guaranteedList2 = nonArrayToArray(valueCanBeListOnObject2);
      const guaranteedList3 = nonArrayToArray(valueCanBeListOnObject3);
      doSomethingOverload(guaranteedList, guaranteedList2, guaranteedList3);
    }

    var doSomethingOverload = (guaranteedList, guaranteedList2, guaranteedList3) => {
      [...guaranteedList, ...guaranteedList2, ...guaranteedList3].forEach(v => console.log(v))
    }
    doSomething('someString',['someString'],1);
  • what is the difference between the treatment int and List get? Could you treat all ints as single item lists? If not, shouldn't these be separate methods since how you deal with each type of variable is too different? – JoseCarlosVM Oct 16 '21 at 17:42
  • 2
    If you are going to write n * n `if...else` branches anyway, why not just write n * n methods? Or are the parameters independent of each other and you only need n `if...else`s? – Sweeper Oct 16 '21 at 17:45
  • 1
    Real life example please! – Caius Jard Oct 16 '21 at 17:55
  • tbh, this looks rather smelly already... why do the arguments come in these formats ... and how would you handle them inside the method generic? pattern matching? type checking?... no gain in code quality over the writing the n*n methods really? – Florian Schmidinger Oct 16 '21 at 18:30
  • What about writing one overload which takes `IEnumerable` and another overload which just passes a single value as an array to the first overload. E.g. `void SomeMethod(IEnumerable varA, string varB) => SomeMethod(varA, new[]{varB});` – Charlieface Oct 16 '21 at 18:37
  • 1
    Even the suggestions for simplifying this are still overcomplicating this. There should be one overload accepting a list of string and a list of ints. Those lists may have a single item in them, if the caller wishes to provide only a single value. No need for more overloads, no need for complex types that may or may not be different things. A list is *already* something that can represent a single value as easily as any other number. – Servy Oct 16 '21 at 19:08
  • @Servy, i do agree that i cannot find a simpler way to do it, and so far the solutions were not ideal for the use case. If c# did accept optional constraints there could be a simple way of doing it but i dont think that is the case. Unless something comes up that gives me a new idea that is my way to go – Mario Figueiredo Oct 17 '21 at 16:16
  • @Sweeper its the second case, i would only need n ```if...else```s – Mario Figueiredo Oct 17 '21 at 16:17

1 Answers1

0

Rule of thumb:

public class SomeMethodArguments
{
   public List<int> WhateverYouWant {get;set;}
}

public void SomeMethod(SomeMethodArguments args);

Looks good. Maps to other arguments. Flexible. Nice quality. Generics in most cases looks like garbage, honestly.

eocron
  • 6,885
  • 1
  • 21
  • 50