95 votes

Comment retourner une valeur avec une méthode anonyme ?

Cela échoue

string temp = () => {return "test";};

avec l'erreur

Impossible de convertir l'expression lambda en type 'string' car ce n'est pas un type de délégué.

Que signifie cette erreur et comment puis-je la résoudre ?

0 votes

Pourquoi cette question est-elle le premier résultat dans Google lorsqu'on recherche l'erreur "anonymous function converted to a void returning delegate cannot return a value" alors qu'elle n'a clairement rien à voir avec cela ?

141voto

JaredPar Points 333733

Le problème ici est que vous avez défini une méthode anonyme qui retourne un string mais vous essayez de l'affecter directement à un string . C'est une expression qui, lorsqu'elle est invoquée, produit une string ce n'est pas directement un string . Il doit être affecté à un type de délégué compatible. Dans ce cas, le choix le plus simple est Func<string>

Func<string> temp = () => {return "test";};

Cela peut être fait en une ligne par un peu de casting ou en utilisant le constructeur du délégué pour établir le type du lambda suivi d'une invocation.

string temp = ((Func<string>)(() => { return "test"; }))();
string temp = new Func<string>(() => { return "test"; })();

Note : Les deux échantillons peuvent être court-circuités à la forme d'expression qui n'a pas l'expression { return ... }

Func<string> temp = () => "test";
string temp = ((Func<string>)(() => "test"))();
string temp = new Func<string>(() => "test")();

0 votes

Merci. Il n'y a donc aucun moyen de tout faire sur une seule ligne (y compris l'assignation de la chaîne) ? La valeur que je veux ("test", qui est en fait une variable dans la vie réelle) est à l'intérieur d'un autre lambda, donc je perds la portée si j'essaie de définir comme vous l'avez fait ci-dessus.

0 votes

@4thSpace on peut le faire en une seule ligne avec un peu de mauvais casting. J'ai mis à jour ma réponse pour montrer le chemin

0 votes

Ou dans ce cas, juste Func<string> temp = () => "test"; .

18voto

Dave Swersky Points 25958

Vous tentez d'attribuer un fonction de délégué à un type de chaîne de caractères. Essayez ceci :

Func<string> temp = () => {return "test";};

Vous pouvez maintenant exécuter la fonction de la manière suivante :

string s = temp();

La variable "s" aura désormais la valeur "test".

8voto

joeriks Points 1107

En utilisant une petite fonction auxiliaire et des génériques, vous pouvez laisser le compilateur déduire le type, et le raccourcir un peu :

public static TOut FuncInvoke<TOut>(Func<TOut> func)
{
    return func();
}

var temp = FuncInvoke(()=>"test");

Remarque : ceci est également intéressant car vous pouvez alors renvoyer un type anonyme :

var temp = FuncInvoke(()=>new {foo=1,bar=2});

0 votes

Technique intéressante. Est-ce que cela ajoute une surcharge au moment de l'exécution, ou est-ce que tout se fait au moment de la compilation ?

0 votes

@ToolmakerSteve : Je pense que cela ajouterait un tout petit peu de temps d'exécution (il s'agit d'envelopper un appel à une méthode anonyme à l'intérieur d'une autre méthode) - cependant, je pense que cela dépendrait également de l'endroit où la méthode FuncInvoke est définie (même assemblage que celui où elle est appelée ou assemblage différent, etc. pourrait être le genre de choses que le compilateur pourrait "mettre en ligne". C'est le genre de question à laquelle les gens répondent en écrivant un programme de test rapide, en le compilant, puis en décortiquant l'IL qui en résulte.

0 votes

@ToolmakerSteve Suite à cette dernière "supposition" concernant l'impact sur les performances, j'ajouterais que même l'impact le plus défavorable que cela aurait sur les performances serait pratiquement nul (un appel de fonction supplémentaire, vers une méthode statique non virtuelle). Quiconque utilise cette technique le fait probablement parce qu'il utilise des lambdas. Cela signifie qu'ils utilisent probablement au moins deux méthodes d'extension LINQ quelque part, et il y a donc de fortes chances qu'ils aient enchaîné par inadvertance deux méthodes LINQ d'une manière qui nuit aux performances 100 000 fois plus qu'un appel de fonction supplémentaire ;)

6voto

HamidReza Points 691

Vous pouvez utiliser la méthode anonyme avec l'argument :

int arg = 5;

string temp = ((Func<int, string>)((a) => { return a == 5 ? "correct" : "not correct"; }))(arg);

0 votes

Vous pouvez, mais expliquez-moi en quoi cela constitue une réponse à la question.

3voto

Debendra Dash Points 1932

Une méthode anonyme peut retourner une valeur en utilisant un délégué func. Voici un exemple où j'ai montré comment retourner une valeur en utilisant une méthode anonyme.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {

        static void Main(string[] args)
        {
            Func<int, int> del = delegate (int x)
              {
                  return x * x;

              };

            int p= del(4);
            Console.WriteLine(p);
            Console.ReadLine();
        }
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X