小编use*_*561的帖子

如何在Delphi 2010下设置泛型类型的前向声明?

我遇到了一个看似非常经典的问题:一个项目和一个集合类,它们都相互引用,需要一个前向声明.我正在使用Delphi 2010和更新5.

这适用于非泛型类,但我无法解决泛型类型的E2086错误:

type
  // Forward declarations
  TMyElement = class; // E2086: Type 'TMyElement' is not yet completely defined

  TMyCollection<T:TMyElement> = class
    //
  end;

  TMyElement = class
    FParent: TMyCollection<TMyElement>;
  end;
Run Code Online (Sandbox Code Playgroud)

切换类声明顺序时会发生同样的问题.

我在这里或在QualityCentral中没有找到任何对此问题的引用(发现了E2086的其他问题,但与此用例无关)

我现在唯一的解决方法是将父项声明为TObject,并在需要时将其强制转换为集合泛型类型(不是一个干净的解决方案......)

您是如何解决此问题,或者向前声明您的泛型类的?

谢谢,

[编辑2011年10月22日]跟进QualityCentral: 我在这里报告了质量中心的这个错误

EMB最近已经关闭,其解决方案状态如下:解决方案:已设计已解决的内容:16.0.4152

我只有Delphi 2010.有人可以确认它已在Delphe XE2 Update1中修复,还是意味着它按预期工作?

[编辑2011年10月23日] EMB的最终答案: EMB今天证实,实际的Delphi编译器不支持使用泛型类型的前向声明.你可以在QC中看到他们的回答,上面提供的链接.

delphi generics forward-declaration

14
推荐指数
1
解决办法
4037
查看次数

如何使用增强的RTTI获取从给定类派生的类列表?

我需要获取表单类型列表,但仅适用于从给定基本表单派生的类型.

我使用Delphi 2010和增强型RTTI来浏览类型

我目前的代码是:

rc := TRTTIContext.Create;
rtyps := rc.GetTypes;
for rtyp in rtyps do
begin
  if not(rtyp.IsInstance) then Continue;

  // Now I need to check if rtyp.AsInstance.MetaclassType is derived from TMyBaseForm
end;
Run Code Online (Sandbox Code Playgroud)

我不想实例化对象并使用'is'运算符,因为它不会及时执行.
作为当前的解决方法,我测试是否在RTTI上下文中找到了在TMyBaseForm中引入的方法:

if (rtyp.GetMethod('MyMethod') = nil) then Continue;
Run Code Online (Sandbox Code Playgroud)

但这不是一个干净的解决方案,因为如果在另一个类分支中引入了具有相同名称的方法,则会导致问题.

所以,我的问题:是否有一种常规方法来检测类类型是否来自另一个类类型?

谢谢,

delphi rtti

13
推荐指数
1
解决办法
1585
查看次数

如何为从TDictionary派生的类创建自定义枚举器?

我已经定义了一个派生自TDictionary的集合,需要定义一个应用额外过滤器的自定义枚举器.

我被卡住,因为我无法访问TDictionary FItems数组(它是私有的)所以我无法定义MoveNext方法

您将如何继续重新定义从TDictionary派生的类的过滤枚举器?

这是一个简单的代码来说明我想要做的事情:

TMyItem = class(TObject)
public
  IsHidden:Boolean; // The enumerator should not return hidden items
end;
TMyCollection<T:TMyItem> = class(TDictionary<integer,T>)
public
   function GetEnumerator:TMyEnumerator<T>; // A value filtered enumerator
   type
     TMyEnumerator = class(TEnumerator<T>)
     private
       FDictionary: TMyCollection<integer,T>;
       FIndex: Integer;
       function GetCurrent: T;
     protected
       function DoGetCurrent: T; override;
       function DoMoveNext: Boolean; override;
     public
       constructor Create(ADictionary: TMyCollection<integer,T>);
       property Current: T read GetCurrent;
       function MoveNext: Boolean;
     end;
end;

function TMyCollection<T>.TMyEnumerator.MoveNext: Boolean;
begin
// In below code, FIndex is not accessible, so I can't …
Run Code Online (Sandbox Code Playgroud)

delphi enumerator tdictionary

9
推荐指数
1
解决办法
1296
查看次数

如何在特定的警告代码上停止Delphi编译器?

我希望编译器在给定警告时停止,就像它是一个错误一样。

目标是强制考虑可能对代码真正有害的警告(并非每个警告在严重性方面都相等)

例如,我希望编译器停止此类警告:

  • 结果可能未初始化
  • 不推荐使用的方法的用法
  • ...

我在IDE中找不到任何选项,也许在命令行编译器中找不到?

德尔福10.3.2

谢谢,

delphi

8
推荐指数
1
解决办法
152
查看次数

固定枚举不返回RTTI属性:它是一个错误吗?

我需要浏览一些类的所有已发布属性.未列出类型为具有固定值的枚举的属性.

见下面的例子:

TMyEnum = (meBlue, meRed, meGreen);
TMyEnumWithVals = (mevBlue=1, mevRed=2, mevGreen=3);
TMyClass =
...
published
  property Color: TMyEnum read FColor write SetColor; // This one is found
  property ColorVal: TMyEnumWithVals read FColorVal write SetColorVal; // This one is never found
end;
Run Code Online (Sandbox Code Playgroud)

我需要固定值,因为这些属性存储在数据库中,我需要确保分配的值始终是相同的,无论下一版本中的Delphi编译器选择如何,并防止在枚举列表中任何错误的未来值插入.

我尝试使用新的Delphi 2010 RTTI(带.GetDeclaredProperties)和"旧"RTTI(带GetPropInfos):除上述类型的属性外,找到所有属性.

在所有类中都可以看到相同的行为.我还在一个示例项目中复制了这个.

尝试使用和不使用各种RTTI指令而不进行更改.

这是一个错误,一个已知的限制?是否有解决方法(除了删除枚举的固定值)?

使用Delphi2010 Ent + Update5

[编辑]答案下面提供变通方法:枚举的第一个值必须被设置为0而不是1,和值是连续的.经过测试和工作的解决方案

谢谢,

delphi rtti

2
推荐指数
1
解决办法
995
查看次数

使用参数检查虚拟方法中的Self = nil

我有两个类:一个基类和一个派生类基类使用参数定义一个虚方法:

function ToName(MsgIfNil:string=''); virtual;
Run Code Online (Sandbox Code Playgroud)

派生类重新定义了该方法:

function ToName(MsgIfNil:string=''); reintroduce;
Run Code Online (Sandbox Code Playgroud)

这两种方法的实现类似于以下代码:

function TBaseClass.ToName(MsgIfNil:string)
begin
  if (Self=nil) then
    Result := MsgIfNil
  else
    Result := Self.SomeProperty;
end;
Run Code Online (Sandbox Code Playgroud)

问题是:

1)如果我没有在派生类中重新引入该方法,但使用常规override关键字,则对此方法的任何调用都会触发访问冲突

2)当我从一个nil的对象调用该方法,并且objet的假定类是TBaseObject时,它崩溃(AV)而不是调用基本虚方法

如果方法中没有定义参数,则调用正确的方法,不带任何AV.即使派生类中的方法被覆盖,它也能很好地工作.

请注意,上述解决方案适用于从TBaseClass派生的任何类的对象

如何定义可以使用Self = nil调用的虚拟方法,可以是虚拟的还是使用参数?

我当然必须加强对内部虚拟方法调用管道工程的理解......

注意:在我的用例中调用nil对象是合法的.它不用于隐藏异常,而是用于报告非链接对象.示例:myEdit.Text:= APerson.Manager.ToName('没有经理定义');

感谢您提供有关正确解决方案的任何建议

使用带有upd5的Delphi 2010


编辑:添加触发AV的更完整的代码示例

TBaseClass = class(TObject)
private
  FMyName: string;
public
  property MyName: string read FMyName;
  function ToName(MsgIfNil:string=''):string; virtual;
end;

TDerivedClass = class(TBaseClass)
private
  FSpecialName: string;
public
  property SpecialName:string read FSpecialName;
  function ToName(MsgIfNil:string=''):string; reintroduce;
end;

TBaseClass.ToName(MsgIfNil:string):string;
begin
   if (Self=nil) then
     Result := MsgIfNil
   else
     Result := …
Run Code Online (Sandbox Code Playgroud)

delphi null access-violation

0
推荐指数
1
解决办法
991
查看次数