delphi – 如果未命名case变量,如何判断变量记录中哪个案例有效,以及如何创建此类记录的值?

我一直在阅读记录中的“案例”,我仍然有一些关于它的开放性问题. (http://www.delphibasics.co.uk/Article.asp?Name=Records)

我用的例子是:

type 
   TRect = packed record
     case Integer of
       0: (Left, Top, Right, Bottom: Integer);
       1: (TopLeft, BottomRight: TPoint);
   end; 

该示例基本上告诉我TRect的第一个成员/属性是一个Integer(这个Integer没有名字!).如果此(未命名!)整数为0或1,则只添加相应的成员:

(0 for Left, Top, Right, Bottom)
(1 for TopLeft, BottomRight) 

所以,让我们说内存中有内容我想用这个记录.
我公平地添加了一个代表TRect指针的新类型.新记录如下所示:

type
   PRect = ^TRect; 
   TRect = packed record
     case Integer of
       0: (Left, Top, Right, Bottom: Integer);
       1: (TopLeft, BottomRight: TPoint);
   end; 

所以内容(在内存中)会像这样排序:

First Integer = 0 // determines the case!
Left          = 1
Top           = 2
Right         = 3
Bottom        = 4

该内容在内存中的总大小为20字节,地址为X.

要输出我的内容,我会像这样输入这个地址:PRect(X)

现在我怎么知道我的唱片有“0”或“1”的情况?!

我怎么能用“0”或“1”的情况创建一个记录?

我对此非常困惑,想知道我是否理解记录中案例的使用……

最佳答案
你没有正确理解. 🙂

记录在内存中始终具有相同的布局,并且始终具有案例部分的0和1部分.您不创建其中一个.使用的是由您自动访问记录的方式决定的;两种情况都存在.

TRect就是一个很好的例子.如果使用Rect函数创建一个新的TRect,那么你有一个包含0和1部分的TRect记录:

var
  R: TRect;
  RTop, RLeft: Integer;
  RTopLeft: TPoint;


  R := Rect(0, 0, 100, 100);
  RTop := R.Top;             // Access TRect.Top separately
  RLeft := R.Left;           // Access TRect.Left separately
  RTopLeft := R.TopLeft;     // Access TRect.TopLeft, which is both Top and Left

  if RTopLeft.X = 0     // This is true, because we created the R rect with 0, 0
                        // as the left and top

  if RTop = 0        // This is also true, for the same reason

另一个如何工作的示例直接来自documentation.您的代码可以使用记录的命名标记部分(Salaried)来确定它应该访问的变体部分的哪个部分.但请注意,这两个部分仍然同时存在.

type
   TEmployee = record
   FirstName, LastName: string[40];
   BirthDate: TDate;
   case Salaried: Boolean of
     True: (AnnualSalary: Currency);
     False: (HourlyWage: Currency);
 end;

var
  Person: TEmployee;

  Person.FirstName := 'John';
  Person.LastName := 'Smith';
  Person.BirthDate := EncodeDate(1980, 1, 1);

AnnualSalary和HourlyWage都存在于内存中;这两种情况中的哪一种取决于您访问哪一种:

  // If this person is paid by the hour
  Person.Salaried := False;
  Person.HourlyWage := 20.00;

  // If this person is paid an annual salary instead
  Person.Salaried := True;
  Person.AnnualSalary := 80000.00;

  // You can access both at the same time. Of course, it wouldn't make
  // any sense to do so in this case.
  if (Person.Salaried and (Person.AnnualSalary > 60000)) then
    DoSomething
  else if (not Person.Salaried) and (Person.HourlyWage > 15.00) then
    DoSomethingElse;

标签名称(由David Heffernan和Free Consulting在评论中指出)占用内存分配空间.

program TestRec;

{$APPTYPE CONSOLE}

uses
  SysUtils;
type
  TTestNoTagName = record    // No tag name on variant part
    I: Integer;
    case Boolean of             
        True: (X, Y: Integer);
        False: (A, B: Integer;)
  end;

type
  TTestWithTagName = record  // Tag name on variant part
    I: Integer;
    case Dummy: Boolean of
      True: (X, Y: Integer);
      False: (A, B: Integer);
  end;

begin
  WriteLn('TTestNoTagName: ', SizeOf(TTestNoTagName));      // SizeOf(12)
  WriteLn('TTestWithTagName: ', SizeOf(TTestWithTagName));  // SizeOf(16)
  ReadLn;
end.

(感谢@davea在初始测试代码中发现错误.)

转载注明原文:delphi – 如果未命名case变量,如何判断变量记录中哪个案例有效,以及如何创建此类记录的值? - 代码日志