Delphi最终尝试了多个对象

时间:2017-03-09 22:15:05

标签: delphi

我写了这段代码:

(function ($, undefined) {
        $.phone1.getCursorPosition = function() {
            var el = $(this).get(0);
            var pos = 0;
            if('selectionStart' in el) {
                pos = el.selectionStart;
            } else if('selection' in document) {
                el.focus();
                var Sel = document.selection.createRange();
                var SelLength = document.selection.createRange().text.length;
                Sel.moveStart('character', -el.value.length);
                pos = Sel.text.length - SelLength;
            }
            return pos;
        }
    })(jQuery);

    $("#phone1").on('keypress', function(e){
        var key = String.fromCharCode(e.which);
        if(key === '*') {
            var position = $(this).getCursorPosition();
            console.log(position);
        } else {
            return false;
        }
    });​

我正在使用firemonkey,因此当我在移动设备上运行时,我不会遇到问题,因为ARC将管理其生命周期。但是当我在Windows上时,这段代码是否安全?

我已经读过,我不能拥有一个finally和一个catch,所以我需要一个嵌套的try块。我想最好的方法就是:

 FD := TList<double>.Create;
 FN := TList<double>.Create;
 RemList := TList<double>.Create;
 dati := TStringList.Create;

 try

  try

   //code

  except
   on E : Exception do 
   ShowMessage('Incorrect values. Error: ' + E.Message);
  end;

 finally

  if Assigned(dati) then
   dati.Free;

  if Assigned(FD) then
   FD.Free;

  if Assigned(FN) then
   FN.Free;

  if Assigned(RemList) then
   RemList.Free;

 end;

我相信我会在任何情况下以安全的方式释放对象,但代码很难阅读。我已经看到Marco Cantu建议在对象pascal手册中使用第二种方法并且我理解它,但在我的情况下我想避免它。

在我编写的第一个代码块中是否会出现错误?

2 个答案:

答案 0 :(得分:2)

如果我是你,我会使用第二段代码,因为你已经知道它更好了; TList<double>.Create(和其他构造函数一样)是&#34;安全&#34;如你所说,但如果你总是认为角落背后存在风险,那就更好了。

请注意,当我说 safe 时,我的意思是如果你以这种方式打电话,他们不会提出异常。在您无法预测的任何情况下都可能发生异常,因此您最终应该尝试保护代码。

您还在使用无用的Assigned()。如果你看一下Free的实现,你会发现这个代码(它也被评论过):

procedure TObject.Free;
begin
// under ARC, this method isn't actually called since the compiler translates
// the call to be a mere nil assignment to the instance variable, which then calls _InstClear
{$IFNDEF AUTOREFCOUNT}
  if Self <> nil then
    Destroy;
{$ENDIF}
end;

Assigned()如果对象等于nil则返回true或false,所以基本上你做了无用的双重检查。

答案 1 :(得分:2)

虽然嵌套try...finally的第二个代码最终以书方式处理对象构造/解构块,但您也可以安全地将它们分组到单个try...finally块中。 / p>

一些可以帮助我们挤压上述代码的事实。

  • 构造函数总是可以抛出异常
  • 析构函数绝不能抛出异常。如果你正在处理破坏了析构函数的类,那么你可能会遇到更大的问题。
  • 非托管局部变量未初始化 - 在包含对象引用的非ARC编译器中。

所以你的代码看起来像这样:

// initialize object references so we can safely use them
FN := nil;
FD := nil;
RemList := nil; 
dati := nil;

try
  FD := TList<double>.Create;
  FN := TList<double>.Create;
  RemList := TList<double>.Create;
  dati := TStringList.Create;

  // do something

finally   
   dati.Free;
   FD.Free;
   FN.Free;
   RemList.Free;
end;

如果任何构造函数失败finally将执行块,并且将清除所有已分配的引用。由于Free在调用实例析构函数之前测试nil,因此在nil引用上调用它是安全的。

以上介绍了如何编写安全的施工/解构链。如果您的执行某些操作代码抛出异常,您可以使用try..except块来处理它,就像您现在正在执行此操作一样。

请记住,上面的代码不处理从构造函数抛出的异常,它只是执行适当的清理。如果要处理可能的构造异常,则必须将代码包含在另一个try...except块中,或者让它们传播到更高级别。

相关问题