如何解决可以使用IF语句调整过程的参数吗?
我有两个几乎相同的过程,唯一的区别是参数之一的数据类型。
procedure InsertNewStringAnswer(AidQuestion: Integer; AAnswer: String);
和
procedure InsertNewBoolAnswer(AidQuestion: Integer; AAnswer: Boolean);
我需要根据问题更改答案类型。我是否必须编写两个过程并用第三个过程调用它们,或者有什么方法可以在运行时更改参数AAnswer的数据类型?
我正在对此进行编辑,以显示如何构建解决方案。在这种情况下,我使用了Variant类型。我无法验证这是否是最佳做法,但可以:)。
procedure InsertNewAnswer(AidQuestion: Integer; AAnswer: Variant);
var
idNextRecord: string;
isBoolean: Boolean;
StrAAnswer: String;
BoolAAnswer: Boolean;
begin
With Connection.queryMain Do
begin
SQL.Clear;
SQL.Text := 'select count(*) as summe from dbo.Answer';
Open;
end;
idNextRecord := Connection.queryMain.FieldByName('summe').Asstring;
With Connection.queryMain Do
begin
SQL.Clear;
//Here I check if the question has a boolean or string answer.
SQL.Text :=('select isBool from dbo.Questions AS ISBOOL WHERE idQuestion= :SQLAidQuestion;');
ParamByName('SQLAidQuestion').AsInteger := AidQuestion;
Prepare;
Open;
end;
//and write it to a Variable.
isBoolean := Connection.queryMain.FieldByName('isBool').AsBoolean;
Connection.queryMain.SQL.Clear;
//I then use a if statement to change the Variant Type accordingly
if isBoolean = True then
begin
//Note that System.Variants does not have VarToBool so I use a workaround
BoolAAnswer := StrToBool(VarToStr(AAnswer));
AAnswer := BoolAAnswer;
Connection.queryMain.SQL.Text :=
('INSERT INTO Frueherkennung.dbo.Answer' +
'(idAnswer,idQuestion,Answer)VALUES(' + idNextRecord +
',:sqlQuestion,:sqlAAnswer);');
Connection.queryMain.ParamByName('sqlQuestion').AsInteger := AidQuestion;
Connection.queryMain.ParamByName('sqlAAnswer').AsBoolean := AAnswer;
end
else
begin
StrAAnswer := VarToStr(AAnswer);
MessageDlg('iSBool:= False',mtError,[mbok],0);
AAnswer := StrAAnswer;
Connection.queryMain.SQL.Text :=('INSERT INTO Frueherkennung.dbo.Answer' +
'(idAnswer,:sqlAAnswer);');
Connection.queryMain.ParamByName('sqlQuestion').AsInteger := AidQuestion;
Connection.queryMain.ParamByName('sqlAAnswer').Asstring := AAnswer
end;
With Connection.queryMain Do
begin
Prepare;
Execute;
SQL.Clear;
end;
end;
感谢大家的精彩回答。
解决方法
如果AAnswer参数的类型可以在其中包含几乎所有内容,则可以编写一个函数。
您还可以使用重载关键字保留两个过程,但名称相同。
您还可以使用单个过程将AAnswer作为指向调用者要使用的存储的无类型指针。当然,此时,问题必须包含必要的信息,以决定该点是指向布尔值还是指向字符串。
实际上不建议使用最后一个选项。对我来说,最干净的解决方案是使用重载过程。
忘记另一种可能性:使用const类型数组的AAnswer。
,听起来像是泛型的工作。
在XE7和更高版本中,您可以执行以下操作:
type
TQuestion = class
public
class procedure InsertNewAnswer<T>(AidQuestion: Integer; AAnswer: T);
end;
class procedure TQuestion.InsertNewAnswer<T>(AidQuestion: Integer; AAnswer: T);
begin
case GetTypeKind(T) of
tkString,tkLString,tkUString,tkWString:
InsertNewStringAnswer(AidQuestion,AAnswer);
tkEnumeration:
if GetTypeData(TypeInfo(T))^.BaseType^ = TypeInfo(Boolean) then
InsertNewBoolAnswer(AidQuestion,PBoolean(@AAnswer)^);
...
end;
end;
在XE7之前,您可以改为:
type
TQuestion = class
public
class procedure InsertNewAnswer<T>(AidQuestion: Integer; AAnswer: T);
end;
...
uses
...,TypInfo;
class procedure TQuestion.InsertNewAnswer<T>(AidQuestion: Integer; AAnswer: T);
begin
case PTypeInfo(TypeInfo(T)).Kind of
tkString:
InsertNewStringAnswer(AidQuestion,PShortString(@AAnswer)^);
tkLString:
InsertNewStringAnswer(AidQuestion,PAnsiString(@AAnswer)^);
tkUString:
InsertNewStringAnswer(AidQuestion,PUnicodeString(@AAnswer)^);
tkWString:
InsertNewStringAnswer(AidQuestion,PWideString(@AAnswer)^);
tkEnumeration:
if GetTypeData(TypeInfo(T))^.BaseType^ = TypeInfo(Boolean) then
InsertNewBoolAnswer(AidQuestion,PBoolean(@AAnswer)^);
...
end;
end;
无论哪种方式,您都可以像这样调用它:
TQuestion.InsertNewAnswer<String>(id,'...');
TQuestion.InsertNewAnswer<Boolean>(id,true);
...
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。