【问题标题】:Is it "supported" to call method on nil reference in Delphi?是否“支持”在 Delphi 中对 nil 引用调用方法?
【发布时间】:2015-11-18 08:21:20
【问题描述】:

下面的 Delphi 程序在 nil 引用时调用方法并且运行良好。

program Project1;

{$APPTYPE CONSOLE}

type
  TX = class
    function Str: string;
  end;

function TX.Str: string;
begin
  if Self = nil then begin
    Result := 'nil'
  end else begin
    Result := 'not nil'
  end;
end;

begin
  Writeln(TX(nil).Str);
  Readln;
end.

但是,在一个结构相似的 C# 程序中,System.NullReferenceException 将被引发,这似乎是正确的做法。

namespace ConsoleApplication1
{
    class TX
    {
        public string Str()
        {
            if (this == null) { return "null"; }
            return "not null";    
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            System.Console.WriteLine(((TX)null).Str());
            System.Console.ReadLine();
        }
    }
}

由于 TObject.Free 使用这种风格,似乎“支持”在 Delphi 中对 nil 引用调用方法。这是真的 ? (假设在if Self = nil 分支中,不会访问任何实例字段。)

【问题讨论】:

标签: c# delphi


【解决方案1】:

nil 引用上调用方法是合理的,遵循以下规则:

  1. 方法不能是虚拟的或动态的。这是因为虚拟或动态方法是使用引用的运行时类型绑定的。如果引用是nil,那么就没有运行时类型。相比之下,非虚拟、非动态方法在编译时绑定。
  2. 您可以读取Self 的值,例如将其与nil 进行比较。
  3. 如果Selfnil,则不能引用任何实例变量。

【讨论】:

  • @XichenLi,VMT表在构造函数中初始化。如果没有初始化,虚拟(动态)调用将不起作用。
  • 我不确定这方面的文档,但我上面所说的正是我所知道的真实情况。
  • @XichenLi 为什么调用常规方法有效?无论如何,它都需要检查 VMT 表中的 vmtMethodTable。 不,不是这样。这些方法是在编译时绑定的。
  • @David - 我认为值得一提的是,编译器不会捕获任何违反这些规则的行为,这样做会导致一般的“访问冲突”异常,而不是更有帮助的诊断错误识别这些规则的具体违规行为(例如,NulLReferenceException)。有经验的开发人员应该能够从访问冲突错误消息的详细信息中推断出 NIL 引用,但它的拼写方式与 .NET 中的特定异常为您所做的不同。
猜你喜欢
  • 2010-10-12
  • 1970-01-01
  • 2021-10-20
  • 2012-09-07
  • 1970-01-01
  • 2012-08-27
  • 2015-01-10
  • 2023-03-16
  • 1970-01-01
相关资源
最近更新 更多