¿Cuál es la diferencia entre Func <string, string> y delegate?

81

Veo delegados en dos formas:

A. Func<string, string> convertMethod = lambda 

B. public delegate string convertMethod(string value);

No estoy seguro de cuál es realmente la diferencia entre estos dos. ¿Ambos son delegados? Creo que el primero usaría una lambda y el segundo tendría que tener un método para realizar el trabajo. Yo también puedo estar confundido.

Dietpixel
fuente

Respuestas:

74

En primer lugar, sus dos ejemplos están haciendo dos cosas totalmente separadas. El primero es declarar una variable delegada genérica y asignarle un valor, el segundo es simplemente definir un delegatetipo. Su ejemplo, más completo, sería:

public static class Program
{
    // you can define your own delegate for a nice meaningful name, but the
    // generic delegates (Func, Action, Predicate) are all defined already
    public delegate string ConvertedMethod(string value);

    public static void Main()
    {
        // both work fine for taking methods, lambdas, etc.
        Func<string, string> convertedMethod = s => s + ", Hello!";
        ConvertedMethod convertedMethod2 = s => s + ", Hello!";
    }
}

Pero más concretamente, ambos Func<string,string>y delegate string convertMethod(string)serían capaces de contener las mismas definiciones de método, ya sean métodos, métodos anónimos o expresiones lambda.

En cuanto a cuál debe utilizar, depende de la situación. Si desea que su delegado se defina más por lo que toma y devuelve, entonces los delegados genéricos son perfectos. Si desea que el delegado tiene un nombre especial que le da una mayor definición de lo que el delegado debe hacer (más allá del simple Action, Predicate, etc), entonces la creación de su propio delegado es siempre una opción.

James Michael Hare
fuente
1
Un ejemplo aún más claro sería Func<int, string>, que muestra que la forma es Func<arg1, result>.
silvalli
6
Creo que vale la pena señalar que Func y Action son delegados. Parece obvio cuando lo sabes, pero estaba asustado por este hecho antes de mirar la firma de Func. Entonces, cuando dices: "En primer lugar, tus dos ejemplos están haciendo dos cosas totalmente separadas". también podría decir: "Func es un delegado".
Falk
12

La muestra de código que tiene confunde un poco las cosas, así que déjeme intentar aclararlo. Los siguientes 2 elementos son declaraciones de delegados. Estos son fáciles de detectar porque siempre contendrán la delegatepalabra clave

public delegate TReturn Func<TArg, TReturn>(Targ value);
public delegate string convertMethod(string value);

Esta línea de código asigna un valor a un local que se escribe a un delegado.

Func<string, string> local = lambda;

Sin embargo, el código anterior no se limita a usar solo lambdas. El valor también podría ser un grupo de métodos compatible u otro valor delegado.

Otro elemento a destacar es que a pesar de que Func<string, string>y convertMethodson ambos delegados con firmas idénticas son sus valores no convertibles entre sí. Por ejemplo, lo siguiente es ilegal

Func<string, string> local1 = ...;
convertMethod local2 = local1; // Error!!!
JaredPar
fuente
8

Desde MSDN ,

En las versiones de C # anteriores a la 2.0, la única forma de declarar un delegado era usar métodos con nombre. C # 2.0 introdujo métodos anónimos y en C # 3.0 y versiones posteriores, las expresiones lambda reemplazan a los métodos anónimos como la forma preferida de escribir código en línea.

y

Hay un caso en el que un método anónimo proporciona una funcionalidad que no se encuentra en las expresiones lambda. Los métodos anónimos le permiten omitir la lista de parámetros. Esto significa que un método anónimo se puede convertir en delegados con una variedad de firmas.

También puede estar interesado en esta respuesta SO sobre la palabra clave delegada frente a la expresión lambda .

Además, MSDN tiene un buen artículo sobre Expresiones Lambda :

delegate int del(int i);
static void Main(string[] args)
{
    del myDelegate = x => x * x;
    int j = myDelegate(5); //j = 25
}

En el ejemplo anterior, observe que la firma del delegado tiene un parámetro de entrada escrito implícitamente de tipo int y devuelve un int. La expresión lambda se puede convertir en un delegado de ese tipo porque también tiene un parámetro de entrada (x) y un valor de retorno que el compilador puede convertir implícitamente al tipo int. (La inferencia de tipos se analiza con más detalle en las siguientes secciones). Cuando se invoca al delegado mediante un parámetro de entrada de 5, devuelve un resultado de 25.

Comunidad
fuente
También puede omitir parámetros de lambda. () => Console.Writeline ("parámetro menos lambda")
Dr Deo
Prueba de acción = () => Console.Writeline ("parámetro menos lambda"); test.Invoke ();
Dr Deo
5

A inicializa una instancia de un delegado (que se puede llamar inmediatamente). Es una variable de tipo Func <string, string>.

B especifica la definición de delegado (su firma). Se puede utilizar para definir posteriormente variables de tipo convertMethod .

fparadis2
fuente