2015-11-18 2 views
9

Следующая программа Delphi вызывает метод по ссылке nil и работает нормально.Поддерживается ли это метод вызова по ссылке nil в Delphi?

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. Это правда ? (Предположим, что в if Self = nil ветви, ни одного поля экземпляра не будет доступен.)

+3

Связанные, http://stackoverflow.com/questions/1040860/why-would-you-check-for-assignedself-in-object-methods –

+0

@HenkHolterman Большое спасибо за ценную информацию! – SOUser

ответ

15

Разумно вызвать метод на nil ссылки, при условии соблюдения следующих правил:

  1. Метод не должен быть виртуальный или динамический. Это связано с тем, что виртуальные или динамические методы связаны с использованием типа среды выполнения. И если ссылка nil, тогда нет типа времени выполнения. В противоположность этому, не виртуальные, нединамические методы связаны с компиляцией времени.
  2. Вы можете прочитать значение Self, например, чтобы сравнить его с nil.
  3. В случае, если Self - nil, то вы не должны обращаться к каким-либо переменным экземпляра.
+0

Большое вам спасибо за помощь! Не могли бы вы прокомментировать, получили ли вы эти правила из официальных документов, особенно в отношении «не виртуальных (или динамических)»? Я так и не нашел официальную страницу документации (или страницу DelphiBasics). – SOUser

+1

@XichenLi, таблица VMT инициализируется в конструкторе. Без инициализации виртуальный (динамический) вызов не работает. –

+1

@XichenLi, см. [Внутренние форматы данных. Типы классов] (http://docwiki.embarcadero.com/RADStudio/en/Internal_Data_Formats#Class_Types). –

Смежные вопросы