是否"支持"在Delphi中调用nil引用方法?

SOU*_*ser 11 c# delphi

以下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.
Run Code Online (Sandbox Code Playgroud)

但是,在结构相似的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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

因为TObject.Free使用这样的样式,所以在Delphi中调用nil引用上的方法似乎是"支持"的.这是真的 ?(假设在if Self = nil分支中,不会访问任何实例字段.)

Dav*_*nan 18

根据nil以下规则在引用上调用方法是合理的:

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

  • @XichenLi*为什么调用常规方法有效?无论如何,它需要检查VMT表中的vmtMethodTable.*不,事实并非如此.这些方法在编译时绑定. (2认同)
  • @David-我认为值得一提的是,编译器不会捕获任何违反这些规则的行为,这将导致通用的“访问冲突”异常,而不是更有用的诊断性错误,这些错误会识别这些规则的特定违法行为(例如NulLReferenceException)。有经验的开发人员应该能够从访问冲突错误消息的详细信息中推断出NIL引用,但其拼写方式与.NET中的特定异常为您提供的方式不同。 (2认同)