Peut un C# expression lambda jamais de retour void?
J'ai la méthode suivante, et je veux savoir s'il ya quelque chose qui peut aller en place par défaut(void) ci-dessous car il y a une erreur de compilation, qui dit que nul n'est pas valide ici:
private void applyDefaultsIfNecessary(ApplicationConfiguration configuration)
{
var defaults = new Dictionary<Predicate<ApplicationConfiguration>, Action<ApplicationConfiguration>>()
{
//{ rule, action } - if rule is true, execute action
{ (c) => c.ConnectionString == null , (c) => c.ConnectionString = "foo" },
{ (c) => c.OutputExcelFilePath == null, (c) => c.ConnectionString = "bar" },
{ (c) => c.OutputDirectory == null, (c) => c.OutputDirectory = "baz" }
};
//Nothing to select, but we want to loop throough the dict and invoke action, if rule is true.
//It is a pity there is no extension method called DoForEach on collections.
defaults.Select((item) => item.Key.Invoke(configuration) ? item.Value.Invoke(configuration) : default(void) );
}
Je me rends compte que je peux utiliser les if-else au lieu de l'opérateur ternaire (ou que je pourrais appeler un mannequin méthode de retour void). Aussi, Sélectionnez la méthode d'extension n'aime pas les lambdas de retour void. Il semble dire que le type ne peut pas être déduit, mais bien sûr, si je spécifier le type de ce genre, soit:
defaults.Select<ApplicationConfiguration, void>((item) => { if (item.Key.Invoke(configuration)) item.Value.Invoke(configuration); } );
J'étais curieux de savoir à partir d'un langage de conception de point de vue, pourquoi nous n'avons pas les expressions qui peuvent retourner void ou le type de données pour des variables est nulle.
Êtes-vous sûr de ne pas dire de retourner la valeur NULL au lieu de void?
Rusanu: Lisez ceci, il y a une bonne raison qui n'a pas été ajoutés. À mon avis, c'est une honte qu'ils l'ont fait sur Liste<T>: blogs.msdn.com/ericlippert/archive/2009/05/18/...
En remplaçant par défaut(vide) avec la valeur null n'aide pas non plus. Le compilateur dit il n'y a pas de implict la conversion entre les nuls et non avenus
Sélectionnez doit retourner quelque chose. Vous ne pouvez pas utiliser une action, sélectionnez - vous de toujours avoir à faire, sélectionnez le retour d'un certain type T, et nul n'est "rien", de sorte qu'il ne fonctionne pas.
OriginalL'auteur Raghu Dodda | 2010-01-08
Vous devez vous connecter pour publier un commentaire.
Je vous renvoie à l'article 7.1 de la norme, qui stipule:
[Emphase ajoutée].
C'est-à-dire que le seul moment où vous pouvez utiliser une expression qui est un vide-retour de l'appel de méthode est lorsque l'expression est une instruction complète. Comme ceci:
Aussi, un
void
expression peut être le côté droit de la=>
lambda flèche. L'ensemble de l'expression, y compris la flèche ne pas avoir un type en lui-même. Et dans le cas où le=>
doit être converti en une arborescence d'expression, qui ne peut pas être writtens comme un bloc avec une seule instruction. Par exempleExpression<Action> tree = () => Console.WriteLine("Hello");
est légal et semble contenir une sous-expression de typevoid
.Expression<Action> tree2 = () => { Console.WriteLine("Hello"); };
ne compile pas car l'instruction corps{ ... }
n'est pas autorisé pour les arbres d'expression.Bon point. Bien sûr, le côté droit d'un opérateur lambda est un contexte dans lequel un expression est légal. Et il m'a toujours paru bizarre qu'il est légal d'avoir "rien" expressions dans une arborescence d'expression. Des arbres d'Expression ont été conçus pour représenter des effets secondaires sans opérations, mais un vide-de retour de la méthode est presque certainement un effet secondaire.
(1) Est "un vide-retour d'invocation de méthode" à la fois une expression et une déclaration? (2) stackoverflow.com/q/44234246/156458
pas de. Une expression instruction se termine par un point-virgule. Une expression qui ne fonctionne pas.
OriginalL'auteur Eric Lippert
C'est, en effet, une violation de la programmation fonctionnelle règles. Cela a le même défaut Eric Lippert décrit à propos de la Liste.ForEach: Vous êtes à la philosphically essayer de provoquer des effets secondaires sur votre collection.
Énumérable.Sélectionnez sert à retourner une nouvelle collection de filtrage de l'entrée. Il n'est pas prévu d'exécuter du code.
Cela étant dit, vous peut contourner ce problème en faisant:
C'est juste pas aussi claire que faire:
+1..merci pour le lien
OriginalL'auteur Reed Copsey
À partir d'un point de vue de la langue,
void
signifie "n'existe pas", ce qui pose la question: quelle est la valeur de y aurait-il dans la déclaration d'une variable qui n'existe pas?Le problème ici n'est pas une restriction de langue, mais le fait que vous êtes en utilisant un concept (l'opérateur ternaire), qui exige deux rvalues -- où vous avez seulement un.
Si je peux être franc, je dirais que vous êtes en évitant si/d'autre en faveur de la inutile de concision. Toutes les astuces que vous venez avec pour remplacer
default(void)
ne servent qu'à embrouiller les autres développeurs, ou vous, dans l'avenir, longtemps après que vous avez cessé de s'embêter avec ce genre de chose.OriginalL'auteur Ben M
Tout d'abord, vous devriez vraiment éviter de mettre de côté les effets de la norme requête linq opérateurs, et d'autre part cela ne fait pas travailler puisque vous n'êtes pas à l'énumération de la requête de sélection n'importe où. Si vous souhaitez utiliser linq, vous pourriez faire ceci:
Concernant votre question, je suis assez sûr il n'y a pas de valeurs possibles de vide et vous ne pouvez pas retourner explicitement. Dans les langages fonctionnels tels que F#, le vide est remplacé par "unité", c'est à dire un type avec une seule valeur possible - si vous vouliez, vous pourriez créer votre propre type d'unité et de retour que. Dans ce cas, vous pourriez faire quelque chose comme ceci:
Mais je ne peux vraiment pas recommander le faire.
OriginalL'auteur Lee
par défaut ne fonctionne pas à vide, mais il fonctionne avec un type. La classe d'Action ne produit pas de résultat, mais la touche Func<> objet doit toujours renvoyer un résultat. N'importe quel élément.De la valeur.Invoke() retourne il suffit de retourner la valeur par défaut qui, comme dans:
par défaut(objet)
ou si c'est un type spécifique:
par défaut(SomeType)
Comme ça.
oui par défaut(<type>) qu'est ce que je dis. Vous devez retourner une valeur par défaut d'un type, pas la nullité. Vous ne pouvez pas faire annuler avec la touche FUnc<>.
OriginalL'auteur Brian Mains