- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
当我调用函数来获取值时,我通常会初始化变量,以防函数失败或不返回任何内容,并且我想避免处理未初始化的变量。我对字符串、整数或任何其他类型执行相同的操作。
整数变量示例:
vPropValue := 0;
vPropValue := GetPropValue(vObject,'Height');
IF vPropValue > 0 Then
...
这是我最常见的使用方式。
我知道我可以使用:
If GetPropValue(vObject,'Height') > 0 Then
...
但在第一个示例中,如果我稍后在代码中再次需要结果,我会避免多次调用函数。
字符串也是如此(尽管我知道本地字符串被初始化为空字符串,而整数不能容纳任何值)
vName := '';
vName := GetObjectName(vObject,'ObjectName');
IF Trim(vPropStrValue) <> '' Then
...
我知道我可以采取措施避免重复赋值,例如确保 Function 在一切失败时返回 0。但我有数百个函数,我不能相信我从来没有犯过函数如何处理所有事情的错误,而且我确信如果一切失败,有些函数不会返回 0。
我试图理解为什么这不是可取的做法以及如何最好地避免它。
编辑
下面是函数未返回正确值或 0 的示例:
function GetValue(vType:integer):integer;
begin
if vType=1 then
Result:=100
else if (vType>2) and (vType<=9) then
Result:=200;
end;
procedure TForm1.Button1Click(Sender: TObject);
var vValue:integer;
begin
vValue:=GetValue(11);
Button1.Caption:=IntToStr(vValue);
end;
在这种情况下,从函数返回的值是一些随机数。
在这种情况下,初始化似乎是有效的方法。 还是不?
编辑2:
正如大卫在回答中指出的那样,正确,有一个警告
[dcc32 Warning] Unit1.pas(33): W1035 Return value of function 'GetValue' might be undefined
但是,我无缘无故地忽略了它,只是没有看那里。因为它让我编译它,所以我认为还可以。因此,我确实查找了警告,并“修复”了相当多具有类似问题的函数,因为所有 IF 结果可能尚未定义。
编辑 3 和结论:
我希望它能扩大问题和解释的范围:
也许我在大多数函数中使用的另一个扭曲的例子也可以解释为什么我认为需要初始化变量,那就是我不确定我的函数是否始终能够正确运行,特别是在这种情况下的嵌套函数。其中大部分仍然是这样设置的:
function GetProperty(vType:integer):integer;
begin
Try
if vType = 99 then
Result:=GetDifferentProperty(vType)// <-- Call to another Function, that could return whatever...
else
begin
if vType=1 then
Result:=100
else if (vType>2) and (vType<=9) then
Result:=200;
end;
except
end;
end;
现在我正在解决这些Try except End;
,但有些函数已经有 10 年历史了,根据我当时的经验,期望它们 100% 工作是不可靠的。
作为该项目的唯一开发人员,我认为我应该信任我的功能(以及我的其余代码),但我无法想象在多个开发人员环境中所有功能都已正确设置。
所以我的结论:由于我没有照顾基础知识 - 正确设计的函数,我需要进行所有这些检查(变量初始化,Try except
行..)以及可能还有其他一些不必要的东西。
最佳答案
假设vPropValue
是一个局部变量,那么这段代码
vPropValue := 0;
vPropValue := GetPropValue(vObject,'Height');
与
没有区别vPropValue := GetPropValue(vObject,'Height');
一个更简单的例子可能是这样的:
i := 0;
i := 1;
将0
分配给i
然后立即将1
分配给i
有什么意义?所以,你肯定不会这么写。你可以写:
i := 1;
在您的代码中,在此答案的顶部,您为同一个变量分配了两次。第一个赋值中分配的值将立即替换为第二个赋值中分配的值。因此,第一个分配毫无意义,应该删除。
第二个示例稍微复杂一些。假设您的函数编写正确,并且始终分配给它们的返回值,并且 vName
是局部变量,那么
vName := '';
vName := GetObjectName(vObject,'ObjectName');
与
没有区别vName := GetObjectName(vObject,'ObjectName');
我添加额外条件的原因与函数返回值的实现的怪癖有关,如下所述。这种情况与上面的情况的区别在于返回值类型。这里它是一个托管类型,string
,而在第一个示例中,该类型是一个简单的Integer
。
同样,考虑到函数总是分配给返回值的附加条件,第一次分配是毫无意义的,因为该值会立即被替换。删除第一个作业。
<小时/>对于您编辑中的函数,如果您启用提示和警告,编译器将警告您其错误的实现。编译器会告诉您并非所有代码路径都会返回值。
function GetValue(vType:integer):integer;
begin
if vType=1 then
Result:=100
else if (vType>2) and (vType<=9) then
Result:=200;
end;
如果两个条件都不满足,则不会为结果变量分配任何值。这个函数应该是:
function GetValue(vType:integer):integer;
begin
if vType=1 then
Result:=100
else if (vType>2) and (vType<=9) then
Result:=200
else
Result:=0;
end;
我无法强调始终从函数返回值有多么重要。事实上,Delphi 甚至允许你的函数被编译,这是一个可怕的弱点。
<小时/>双重赋值有时对您有用的原因是 Delphi 中函数返回值实现的一个怪癖。与几乎所有其他语言不同,某些更复杂类型的 Delphi 函数返回值实际上是一个 var
参数。所以这个函数
function foo: string;
实际上,在语义上,与此相同:
procedure foo(var result: string);
这是德尔福设计师做出的一个非常奇怪的决定。在大多数其他语言中,如 C、C++、C#、Java 等,函数返回值就像从被调用者传递到调用者的按值参数。
这意味着,如果您愿意,您可以通过函数的返回值将值传递给函数。例如,考虑以下代码:
// Note: this code is an example of very bad practice, do not write code like this
function foo: string;
begin
Writeln(Result);
end;
procedure main;
var
s: string;
begin
s := 'bar';
s := foo;
end;
当你调用main
时,它会输出bar
。这是一个相当奇怪的实现细节。你不应该依赖它。让我重复一遍。你不应该依赖它。不要养成在调用站点初始化返回值的习惯。这会导致代码无法维护。
而是遵循简单的规则,确保函数返回值始终由函数分配,并且在分配之前绝不读取。
<小时/>有关函数返回值实现的更多详细信息由 documentation 提供。 ,我强调的是:
The following conventions are used for returning function result values.
- Ordinal results are returned, when possible, in a CPU register. Bytes are returned in AL, words are returned in AX, and double-words are returned in EAX.
- Real results are returned in the floating-point coprocessor's top-of-stack register (ST(0)). For function results of type Currency, the value in ST(0) is scaled by 10000. For example, the Currency value 1.234 is returned in ST(0) as 12340.
- For a string, dynamic array, method pointer, or variant result, the effects are the same as if the function result were declared as an additional var parameter following the declared parameters. In other words, the caller passes an additional 32-bit pointer that points to a variable in which to return the function result.
- Int64 is returned in EDX:EAX.
- Pointer, class, class-reference, and procedure-pointer results are returned in EAX.
- For static-array, record, and set results, if the value occupies one byte it is returned in AL; if the value occupies two bytes it is returned in AX; and if the value occupies four bytes it is returned in EAX. Otherwise, the result is returned in an additional var parameter that is passed to the function after the declared parameters.
关于delphi - 变量应该在调用函数之前初始化吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33927750/
C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: ?
最近,我有一个关于工作预评估的问题,即使查询了每个功能的工作原理,我也不知道如何解决。这是一个伪代码。 下面是一个名为foo()的函数,该函数将被传递一个值并返回一个值。如果将以下值传递给foo函数,
CStr 函数 返回表达式,该表达式已被转换为 String 子类型的 Variant。 CStr(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CSng 函数 返回表达式,该表达式已被转换为 Single 子类型的 Variant。 CSng(expression) expression 参数是任意有效的表达式。 说明 通常,可
CreateObject 函数 创建并返回对 Automation 对象的引用。 CreateObject(servername.typename [, location]) 参数 serv
Cos 函数 返回某个角的余弦值。 Cos(number) number 参数可以是任何将某个角表示为弧度的有效数值表达式。 说明 Cos 函数取某个角并返回直角三角形两边的比值。此比值是
CLng 函数 返回表达式,此表达式已被转换为 Long 子类型的 Variant。 CLng(expression) expression 参数是任意有效的表达式。 说明 通常,您可以使
CInt 函数 返回表达式,此表达式已被转换为 Integer 子类型的 Variant。 CInt(expression) expression 参数是任意有效的表达式。 说明 通常,可
Chr 函数 返回与指定的 ANSI 字符代码相对应的字符。 Chr(charcode) charcode 参数是可以标识字符的数字。 说明 从 0 到 31 的数字表示标准的不可打印的
CDbl 函数 返回表达式,此表达式已被转换为 Double 子类型的 Variant。 CDbl(expression) expression 参数是任意有效的表达式。 说明 通常,您可
CDate 函数 返回表达式,此表达式已被转换为 Date 子类型的 Variant。 CDate(date) date 参数是任意有效的日期表达式。 说明 IsDate 函数用于判断 d
CCur 函数 返回表达式,此表达式已被转换为 Currency 子类型的 Variant。 CCur(expression) expression 参数是任意有效的表达式。 说明 通常,
CByte 函数 返回表达式,此表达式已被转换为 Byte 子类型的 Variant。 CByte(expression) expression 参数是任意有效的表达式。 说明 通常,可以
CBool 函数 返回表达式,此表达式已转换为 Boolean 子类型的 Variant。 CBool(expression) expression 是任意有效的表达式。 说明 如果 ex
Atn 函数 返回数值的反正切值。 Atn(number) number 参数可以是任意有效的数值表达式。 说明 Atn 函数计算直角三角形两个边的比值 (number) 并返回对应角的弧
Asc 函数 返回与字符串的第一个字母对应的 ANSI 字符代码。 Asc(string) string 参数是任意有效的字符串表达式。如果 string 参数未包含字符,则将发生运行时错误。
Array 函数 返回包含数组的 Variant。 Array(arglist) arglist 参数是赋给包含在 Variant 中的数组元素的值的列表(用逗号分隔)。如果没有指定此参数,则
Abs 函数 返回数字的绝对值。 Abs(number) number 参数可以是任意有效的数值表达式。如果 number 包含 Null,则返回 Null;如果是未初始化变量,则返回 0。
FormatPercent 函数 返回表达式,此表达式已被格式化为尾随有 % 符号的百分比(乘以 100 )。 FormatPercent(expression[,NumDigitsAfterD
FormatNumber 函数 返回表达式,此表达式已被格式化为数值。 FormatNumber( expression [,NumDigitsAfterDecimal [,Inc
我是一名优秀的程序员,十分优秀!