Est-il, ou est-il jamais, un opérateur conditionnel en Delphi?
j'ai gardé mes mains loin de Delphi trop longtemps, je suppose; occupé moi-même avec Java et PHP beaucoup au cours des deux dernières années. Maintenant, quand je suis revenu à faire un petit travail Delphi, j'ai réalisé que l'opérateur conditionnel qui est supporté à la fois par Java et PHP me manquait vraiment.
sur combien d'endroits trouveriez-vous des lignes comme celles-ci dans vos programmes Delphi?
var s : string;
begin
...<here the string result is manipulated>...
if combo.Text='' then
s := 'null'
else
s := QuotedStr(combo.Text);
result := result + s;
end;
où un simple
result := result + (combo.text='')?'null':quotedStr(combo.text);
suffirait. Quel J'aime à ce sujet est que non seulement il raccourcit le code, de cette façon j'évite également de déclarer certains helper s:string
variable.
pourquoi les opérateurs conditionnels ne font - ils pas partie de Delphi et-vont-ils jamais être pris en charge? J'ai remarqué qu'il y avait pas mal d'extensions linguistiques pour la version 2009 de Delphi (génériques), alors pourquoi ne pas ajouter cette fonctionnalité?
10 réponses
un tel opérateur ne fait pas partie de la version Delphi actuelle car il ne faisait pas partie de la version précédente, et la demande n'était pas assez grande pour justifier le coût de l'ajout. (Vous trouverez cette explication s'applique à beaucoup de fonctionnalités que vous aimeriez avoir en beaucoup de produits.)
Delphi fournit un ensemble de IfThen
fonctions dans les unités mathématiques et StrUtils, mais ils ont la propriété malheureuse d'évaluer tous les deux leurs paramètres de valeur, de sorte que le code comme celui-ci échouera:
Foo := IfThen(Obj = nil, '<none>', Obj.Name);
pour vraiment le faire correctement, il faut l'aide du compilateur. Dans la communauté Delphi, je sens une aversion générale pour la syntaxe du style C en utilisant un point d'interrogation et deux points. J'ai vu des propositions qui utiliseraient une syntaxe comme celle-ci:
Foo := if Obj = nil then
'<none>'
else
Obj.Name;
une partie de ce qui rend les opérateurs conditionnels si attrayants est qu'ils vous laissent écrire du code concis, mais le style de Delphi de écrire tout rend ce qui précède peu attrayant, même si mis tous sur une ligne.
Il n'a pas vraiment besoin d'être dans la forme d'un opérateur . Delphi Prism fournit une fonction de compilation-magie Iif
qui évalue seulement un de ses deux paramètres de valeur:
Foo := Iif(Obj = nil, '<none>', Obj.Name);
vous avez demandé pourquoi une fonctionnalité comme celle-ci n'aurait pas été ajoutée avec toutes les autres fonctionnalités linguistiques ajoutées dans Delphi 2009. Je pense que c'est votre raison. Il y avait beaucoup d'autres changements de langage en cours qui nécessitaient déjà une manipulation délicate; les développeurs n'avaient pas besoin d'être surchargés avec encore plus. Les fonctionnalités ne sont pas gratuites.
vous avez demandé si Delphi aura jamais un tel dispositif. Je ne suis pas au courant des réunions de planification D'Amarcadero, et j'ai dû envoyer ma boule de cristal loin pour les réparations, donc je ne peux pas dire avec certitude, mais je prédis que si jamais aurait avoir un tel caractéristique, il viendrait sous la forme de prisme Delphi Iif
fonction. Cette idée apparaît vers la fin de dans la discussion de qualité Centrale , et on objecte que, en tant que nouveau mot réservé, il briserait la rétrocompatibilité avec le code d'autres personnes qui définit déjà une fonction avec le même nom. Ce n'est pas un objet valide, parce que ça n'aurait pas besoin d'être un mot réservé. Il pourrait s'agir d'un identifiant, et tout comme Writeln
et Exit
, il peut être admissible à être redéfini dans d'autres unités, même si celui de l'unité du Système est spécialement traités.
Ok. Code WTF du jour:)
comment obtenir quelque chose qui agit principalement comme une fonction ternaire/conditionnelle.
program Project107;
{$APPTYPE CONSOLE}
uses SysUtils;
type
TLazyIfThen<T:record>=record
class function IfThen(aCondition:Boolean;aIfTrue, aIfFalse:TFunc<T>):T; static;
end;
class function TLazyIfThen<T>.IfThen(aCondition:Boolean;aIfTrue, aIfFalse:TFunc<T>):T;
begin
if aCondition then
Result := aIfTrue
else
Result := aIfFalse
end;
begin
WriteLn(
TLazyIfThen<Integer>.IfThen(
True,
function:Integer begin result := 0 end,
function:Integer begin result := 1 end
)
);
ReadLn;
end.
Oui, c'est plus ou moins inutile, mais ça montre que c'est faisable.
il existe un certain nombre de poignées simples disponibles sur la fonction IFTHEN surchargée.
StrUtils.IfThen
( String
)
Math.IfThen
( Integer
)
Math.IfThen
( Int64
)
Math.IfThen
( Double
) (fonctionne pour TDateTime
ainsi)
Ce modèle tombe comme indiqué dans L'exemple que Andreas a commenté, mais pour les types simples c'est plus que raisonnable. Si suit la convention Delphi/Pascal de méthodes plutôt que de succomber à la manière D'utiliser le moins de caractères possible.
personnellement, je ne voudrais pas voir un opérateur conditionnel (i.e. ?:
) introduit dans Delphi car je préfère la lisibilité de Delphi/Pascal plutôt que C et les langues dérivées de l'informatique. Je préférerais voir des solutions plus innovantes de type Delphi pour quelque chose comme ça que de mettre en œuvre de plus, C-ismes.
il n'y a pas d'opérateur conditionnel à Delphi, et je doute sérieusement qu'il y en ait un, mais vous ne le saurez peut-être jamais. Vous pouvez toujours faire une demande à L'Embarcadero.
une alternative consiste à définir la fonction Iff:
function Iff(const ACondition: Boolean; const ATrueValue, AFalseValue: XXX): XXX;
begin
if ACondition then
Result := ATrueValue
else
Result := AFalseValue;
end;
où XXX est le type desirec.
utiliser comme:
Result := Result + Iff(combo.text='', 'null', quotedStr(combo.text));
il y a plusieurs raisons pour ne pas mettre en œuvre l'opérateur conditionnel. L'un de ces est lisibilité. Pascal (et aussi Delphi) est plus centré sur la lisibilité que les langages de syntaxe C qui sont plus centrés sur la puissance de caractère (autant d'informations par caractère que possible). L'opérateur conditionnel est puissant mais (selon certains) non lisible. Mais si vous regardez le (redouté) avec la déclaration dans Delphi... (pas besoin d'en dire plus). Une autre raison est que l'opérateur conditionnel n'est pas nécessaire. Ce qui est vrai. Mais il y a plus pas nécessaire qui est encore mis en œuvre.
au final, c'est juste une question de goût.
mais si vous voulez qu'un seul argument soit évalué, Vous pouvez toujours utiliser le folowing, qui viole à la fois la lisibilité comme le concept de puissance de caractère:
[overdesignmode]
// Please don't take this that serious.
type
TFunc = function(): XXX;
function Iff(const ACondition: Boolean; const ATrueFunc, AFalseFunc: TFunc): XXX;
begin
if ACondition then
ATrueFunc
else
AFalseFunc;
end;
[/overdesignmode]
je préfère de mettre en œuvre l'évaluation différée et il sera plus puissant et peut être utilisé dans différents scénario. Voir le détail sous le lien
http://www.digitalmars.com/d/2.0/lazy-evaluation.html
Cheers
en fait pour les cordes vous pouvez utiliser le: StrUtils.IfThen fonction:
function IfThen(AValue: Boolean;
const ATrue: string;
AFalse: string = ): string; overload;
regardez dans le wiki d'aide delphi: http://docwiki.embarcadero.com/VCL/en/StrUtils.IfThen
il fait exactement ce dont vous avez besoin.
une autre option est d'utiliser des génériques:
Cond<T> = class
public class function IIF(Cond: boolean; IfVal: T; ElseVal: T): T;
end;
implementation
class function Cond<T>.IIF(Cond: boolean; IfVal, ElseVal: T): T;
begin
if Cond then
Result := IfVal
else
Result := ElseVal;
end;
c'est tout à fait lisible:
var MyInt: Integer;
begin
MyInt:= Cond<Integer>.IIF(someCondition, 0, 42);
remarque: comme l'a souligné Alan Bryant (à 6/21/2004 7:26:21 AM) QR 8451 , ce sera toujours évaluer tous les 3 arguments - donc être conscient que ce n'est pas un vrai opérateur ternaire.
encore mieux est un IIF surchargé (inline if) qui supporte plusieurs types de données et de résultats.
Jedi Code Library ( JCL ) a implémenté l'opérateur ternaire avec un ensemble de fonctions nommées Iff(). Voir ici pour la documentation:
http://wiki.delphi-jedi.org/wiki/JCL_Help:Iff@Boolean@Boolean@Boolean
pour télécharger JCL vous pouvez visiter ce site: