C#: opérateur implicite et les méthodes d'extension
Je suis en train de créer un PredicateBuilder<T>
classe qui encapsule une Expression<Func<T, bool>>
et fournit des méthodes pour construire facilement une expression avec divers And
et Or
méthodes. J'ai pensé qu'il serait cool si je pouvais utiliser cette PredicateBuilder<T>
comme un Expression<Func<T, bool>>
directement, et de la pensée de ce qui pourrait être fait par la présence d'une implicit operator
méthode chose.
Version allégée de la classe ressemble à ceci:
class PredicateBuilder<T>
{
public Expression<Func<T, bool>> Predicate { get; protected set; }
public PredicateBuilder(bool initialPredicate)
{
Predicate = initialPredicate
? (Expression<Func<T, bool>>) (x => true)
: x => false;
}
public static implicit operator Expression<Func<T, bool>>(
PredicateBuilder<T> expressionBuilder)
{
return expressionBuilder.Predicate;
}
}
Alors, un peu comme un test, j'ai cette extension de la méthode dans une classe statique:
public static void PrintExpression<T>(this Expression<Func<T, bool>> expression)
{
Console.WriteLine(expression);
}
Dans ma tête, je dois être capable de faire ceux-ci:
var p = new PredicateBuilder<int>(true);
p.PrintExpression();
PredicateExtensions.PrintExpression(p);
Cependant aucune de ces travaux. Pour la première, la méthode d'extension qui n'est pas trouvé. Et pour le second, il est dit que
Le type des arguments de la méthode 'ExtravagantExpressions.PredicateHelper.PrintExpression(Système D'.Linq.Les Expressions.L'Expression>) " ne peut pas être déduit à partir de l'utilisation. Essayez de spécifier le type des arguments explicitement.
J'ai donc essayé la suivante, ce qui a fonctionné:
PredicateExtensions.PrintExpression<int>(p);
Aussi, cela fonctionne, bien sûr:
((Expression<Func<int, bool>>) p).PrintExpression();
Mais ouais... pourquoi ne pas les autres? Ai-je mal compris quelque chose sur la façon dont cette implicit operator
chose qui fonctionne?
OriginalL'auteur Svish | 2009-03-26
Vous devez vous connecter pour publier un commentaire.
Ce n'est pas spécifique à des méthodes d'extension. C# ne implicitement associer un objet à un autre type, sauf s'il existe un indice sur le type de cible. Supposons ce qui suit:
Quelle méthode peut-on s'attendre à être appelé dans l'instruction suivante?
Je m'attends à "Foo() est ambigu: B. Foo() ou C. Foo()"
C'est possible, mais ne ferait que compliquer la langue et, éventuellement, de cacher les effets secondaires. Et après tout, comment auriez-vous réagi si un code de travail soudain des pauses lorsque vous définissez un nouvel opérateur implicite sur une classe 🙂 C'est juste plus simple pour forcer le type explicite de la déclaration de partout.
Il ne fonctionnera pas si vous êtes seulement à faire avec deux classes (
A
etB
). Retrait de laC
classe complètement à partir de votre exemple donne toujours l'erreur “CS1061: Type 'A' ne contient pas une définition pour 'Foo' et aucune méthode d'extension 'Foo' de type 'A' a pu être trouvé (vous manque une directive using ou une référence d'assembly?)”. Vous avez besoin pour obtenirimplicit
's en cas d'utilisation correcte avant de vous approcher de la coulée de plusieurs classes différentes.Ce n'est pas le point. Ce code est hypothétique pour C# en quelque sorte l'appui de cette fonctionnalité, démontrant les problèmes qu'elle entraîne. Bien sûr, il ne fonctionne pas.
OriginalL'auteur Mehrdad Afshari
Non, vous n'avez pas, mais le compilateur C# de type déduction n'est pas assez puissant pour comprendre votre code, et en particulier, il n'a pas l'air au implicite des opérateurs. Vous aurez à coller avec
Expression<Func<T,bool>>
— pourquoi ne pas avoir des méthodes d'extension commeOr
,And
directement sur des expressions?Je dirais "idéalement" cela devrait fonctionner 🙂 donc, il n'est pas assez puissant pour savoir où chercher.
Déjà ces méthodes d'extension. Mais je vais essayer de rendre les choses un peu plus facile de travailler avec lors de la construction des expressions de ce genre. Vous ne savez pas si je vais réussir :p
Bonne chance quand même ^.^
OriginalL'auteur Anton Tykhyy
Anton dit, si vous mettez les méthodes d'extension directement sur
Expression<Func<...>>
il serait sans doute travailler.Plus d'explication... rien de particulièrement intelligent, mais l'idée serait que vous n'avez pas de
PredicateBuilder
classe que vous en créer des instances. Au lieu de cela, vous avez juste purement statique blocs de construction:Ces deux fonctions
True
etFalse
jouer le rôle de votrePredicateBuilder(bool)
constructeur, et vous auriez probablement similaires à celles pour les primitives des comparaisons et ainsi de suite, et d'opérateurs commeAnd
vous permet de brancher deux expressions.Cependant, vous perdez la possibilité d'utiliser l'opérateur de symboles, qui vous pourriez avoir avec votre objet wrapper, et au lieu de cela, vous devez utiliser les noms de méthode. J'ai été jouer avec le même genre de démarches, de la chose et je reviens toujours, c'est que je veux être en mesure de définir l'extension des opérateurs. L'équipe C#, apparemment ces pour la 3.0 (avec extension de propriétés), mais ils ont été plus faibles prioritaires parce qu'ils n'ont pas de jouer un rôle dans l'ensemble des objectifs de Linq.
Expression<Func<...>>
"? N'est-ce pas ce que j'ai déjà fait? Ou voulez-vous dire de l'utiliser sur uneExpression<Func<T, bool>>
au lieu de sur unPredicateBuilder<T>
? (C'était juste une utilisation normale, et des œuvres, bien sûr)Voir l'explication.
Je ne comprends pas...
Oh, l'homme, la chose que j'ai posté n'est jamais apparu! Désolé à ce sujet.
Il est là maintenant. J'espère que c'est pas une déception, après une longue accumulation!
OriginalL'auteur Daniel Earwicker