2012-06-26 14 views
10

Recientemente comencé a explorar expresiones lambda y me vino a la mente una pregunta. Supongamos que tengo una función que requiere un número indeterminado de parámetros. Usaría la palabra clave params para modelar esa cantidad variable de parámetros.¿Pueden los parámetros [] ser parámetros para una expresión lambda?

Mi pregunta: ¿puedo hacer algo similar con las expresiones Lambda? Por ejemplo:

Func<int[], int> foo = (params numbers[]) => 
         { 
          int result; 

          foreach(int number in numbers) 
          { 
           result += numbers; 
          } 

          return result; 
         } 

Si es así, dos sub-preguntas se presentan - hay una manera de 'bueno' para escribir una expresión tal, y tendrían que incluso desee escribir una expresión como ésta en algún momento?

+0

posible duplicado de [parámetros variables en C#] Lambda (http://stackoverflow.com/questions/3581118/variable-parameters-in-c-sharp-lambda) –

+0

me pregunto si en realidad se puede llamar a eso una expresión lambda , Creo que es un método anónimo. –

+1

@YuriyFaktorovich: Es una lambda. The => es el operador lambda. –

Respuesta

13

Bueno, más o menos. En primer lugar, en lugar de utilizar Func<>, lo que se necesita para definir un delegado de encargo:

public delegate int ParamsFunc (params int[] numbers); 

Entonces, se podría escribir un siguiente lambda:

ParamsFunc sum = p => p.Sum(); 

Y lo debe invocar con número variable de argumentos:

Console.WriteLine(sum(1, 2, 3)); 
Console.WriteLine(sum(1, 2, 3, 4)); 
Console.WriteLine(sum(1, 2, 3, 4, 5)); 

Pero para ser honesto, es mucho más sencillo quedarse con los delegados incorporados Func<>.

+2

Esto era exactamente lo que estaba buscando. Gracias: D –

2

Lo más cercano que creo que se puede conseguir sería algo como esto:

Func<int[], int> foo = numbers[] => 
         { 
          // logic... 
         } 

var result = foo(Params.Get(1, 5, 4, 4, 36, 321, 21, 2, 0, -4)); 

Y tener:

public static class Params 
{ 
    public static T[] Get(params T[] arr) 
    { 
     return arr; 
    } 
} 

Pero no puedo ver cómo que late un simple new[] {1, 5, 4, 4, ...}

1

Hay dos cosas aquí, el delegado genérico Func<int[], int> en el LHS y la expresión lambda en el RHS. El primero no es posible, ya que un delegado Func<S, T> se declara como:

public delegate TResult Func<in T, out TResult>(T arg); //ie no params involved 

usted necesita su propio delegado que acepta params de entrada como se muestra en la respuesta aceptada.

Este último, que es de lo que se trata el título de la pregunta, no es posible también en C#, pero por algún motivo.

El LHS de una expresión de asignación es una cosa en tiempo de compilación (a menos que sea dynamic, por supuesto, pero de nuevo compilador es consciente de ello) y su lado derecho es una cosa de tiempo de ejecución (a menos que, por supuesto, en el caso de const s). El compilador puede inferir lo que se tipea en LHS, pero obtiene los valores en RHS solo durante el tiempo de ejecución, es decir, cuando se ejecuta el código. Al escribir esto:

Func<int[], int> foo = .... 

foo siempre se considera como Func<int[], int>. Agregará mucha complejidad al compilador si tuviera que descifrar RHS. Por ej.Si lo que estás intentando era posible, piense en este escenario:

Func<int[], int> foo = (params int[] numbers) => 
        { 
         int result; 

         foreach(int number in numbers) 
         { 
          result += numbers; 
         } 

         return result; 
        }; 

//and later at some other place 
foo = (int[] numbers) => 0; 

//how would you call 'foo' now? 

lugar cuando se escribe su propio delegado que acepta params, usted está diciendo al compilador directamente (es decir, conocidos a partir LHS).

De las tres características que los parámetros de un soporte método llamado, es decir, out/ref, params, parámetro opcional, las expresiones lambda (o incluso el anterior delegate sintaxis) de apoyo solamente out/ref.

Cuestiones relacionadas