Why don't Funcs accept more than 16 arguments?

后端 未结 6 971
情话喂你
情话喂你 2021-02-05 04:54

Since Javascript is the language that I am the most proficient at, I am familiar with using functions as first-class objects. I had thought that C# lacked this feature, but then

相关标签:
6条回答
  • 2021-02-05 05:11

    Why is there a limit anyway?

    There is opinion that function probably should not have more than 3 arguments. If it has more, it becomes increasingly harder to understand. Of course this may not be the reason why it is this way in C#, but this limitation may not be such a bad thing after all.

    I would argue that even this limit of 16 is way too much and is encouraging bad design choices already.

    0 讨论(0)
  • 2021-02-05 05:19

    You're hoping for something like variadic type arguments which C# lacks. C# requires the arity of generic types to be fixed, therefore the heinous proliferation of Func, Action, and Tuple types.

    If you're language shopping, this feature was added in C++11, but you should probably just use jQuery. :-)

    0 讨论(0)
  • 2021-02-05 05:20

    System.Func delegates are probably there thanks to the BCL team.. who realised including a finite number of predefined generic delegates would be handy (and even required for a lot of situations).

    To do what you say.. i.e. unlimited number of generic parameters for a Func delegate would require a language change.. the responsiblity would lie with both c# and vb.net teams (and the others probably) to change the language to allow this.

    Maybe, at some point, if the benefit of this feature outweighs the cost of predefining a handful of Func delegates and this is more important than other language changes (and that it isn't a breaking change) the relevent teams my implement unlimited generic parameters.. might not be for a while though!

    0 讨论(0)
  • 2021-02-05 05:21

    You can create your own delegate with more than 16 arguments. Or you can use Tuple<T1, T2, T3, T4, T5, T6, T7, TRest> (or any other data structure) as parameter.

    0 讨论(0)
  • 2021-02-05 05:24

    I think I understand - what you can do with JavaScript and functions (arguments) is preaty neat but it's also not statically typed.

    But please note that you never need more than one argument in functional programming anyway. You can chain as much argument as you like by returning another function (this is a common trait in FP and heavaly used with curring a technique also avaiable in JS but only with bending the system a bit).

    Of course this is ackward in C#:

    Func<A1,Func<A2,Func<A3,...<Func<An,Result>>...> 
      x1 =>
        (x2 => 
          (x3 => 
            ... 
              (xn => 
                  { /*return soomething */ }
      ))...);
    

    but this is what F# is for ;) and of course you should never make a function with more than a few arguments (way below 16!) anyhow.

    0 讨论(0)
  • 2021-02-05 05:30

    You can just define any delegate you need. So a Func with 20 parameters would be defined like this:

    public delegate R Func<
        P0, P1, P2, P3, P4, P5, P6, P7, P8, P9,
        P10, P11, P12, P13, P14, P15, P16, P17, P18, P19, R>(
            P0 p0, P1 p1, P2 p2, P3 p3, P4 p4,
            P5 p5, P6 p6, P7 p7, P8 p8, P9 p9,
            P10 p10, P11 p11, P12 p12, P13 p13, P14 p14,
            P15 p15, P16 p16, P17 p17, P18 p18, P19 p19);
    

    You could then use it like this:

    Func<
            int, int, int, int, int, int, int, int, int, int,
            int, int, int, int, int, int, int, int, int, int, int> f = (
                p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10,
                p11, p12, p13, p14, p15, p16, p17, p18, p19) =>
                    p0 + p1 + p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9 + p10
                        + p11 + p12 + p13 + p14 + p15 + p16 + p17 + p18 + p19;
    
    var r = f(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
    

    C# also lets you use lambda syntax on any delegate, so you could also do this:

    public delegate R ArrayFunc<P, R>(params P[] parameters);
    

    And then use it like so:

    ArrayFunc<int, int> af = ps => ps.Sum();
    
    var ar = af(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1);
    

    It's a very flexible and powerful feature of the language.

    0 讨论(0)
提交回复
热议问题