【问题标题】:Generic method in property write属性写入中的通用方法
【发布时间】:2021-12-06 19:18:03
【问题描述】:

我想出了以下易于扩展的"bit bucket"

unit BitBucket;

interface

type TBitBucket = class
private
  class procedure ThrowAway<T>(value: T); static;
public
  class property Integer: Integer write ThrowAway;
  class property String_: String write ThrowAway;
  class property Extended: Extended write ThrowAway;
  class property Boolean: Boolean write ThrowAway;
end;

implementation

class procedure TBitBucket.ThrowAway<T>(value: T);
begin
end;

end.

但是,虽然 IDE 中没有波浪线下划线,但它无法编译,并出现以下错误:

[dcc32 错误] BitBucket.pas(9): E2008 不兼容类型
[dcc32 错误] BitBucket.pas(10): E2008 不兼容类型
[dcc32 错误] BitBucket.pas(11): E2008 不兼容类型
[dcc32 错误] BitBucket.pas(12): E2008 类型不兼容

我是否缺少一个可以编译的技巧?我尝试将泛型类型参数指定为ThrowAway,但这会导致更多错误。显而易见的替代方法是为每种类型编写一个ThrowAway 方法,但这很快会导致很多代码实际上什么都不做。


对于那些想知道为什么在 delphi 中,您可以使用编译器开关来防止使用函数而不分配它们的返回值以与旧代码兼容的人。使用 BitBucket,您可以说 BitBucket.Integer := FunctionThatHasSideEffectsAndReturnsAnInteger(...);,而无需创建新变量。我也觉得很好笑。

【问题讨论】:

  • Delphi 泛型比它的 C++ 泛型更受限制。无论如何,丢弃函数的结果是完全有效的。你说的那个开关是默认开启的。
  • 快速但丑陋且相当愚蠢的解决方案:procedure ThrowAway(const X: Variant); begin end;
  • @AndreasRejbrand 在参数列表中使用const Xconst X: Variant 只会导致相同的错误。
  • const X 不起作用,但 const X: Variant 起作用。 privat.rejbrand.se/ThrowAway.pas
  • 啊,我明白你现在的意思了,但这并不是真正使用相同的 bitbucket 模拟。我正在尝试发现类和属性的功能。顺便说一句,我之前在 RAD Studio 10.2 中工作,在 10.4 下做同样的事情确实会给代码红色波浪线。

标签: delphi


【解决方案1】:

您将泛型与变体混淆了。你需要这样的东西:

unit BitBucket;

interface

type 
  TBitBucket<T> = class
  private
    class procedure ThrowAway(const Value: T); static;
    class var FVar: T;
  public
    class property MyProperty: T read FVar write ThrowAway;
  end;

implementation

class procedure TBitBucket<T>.ThrowAway(const Value: T);
begin
  FVar := Value;
end;

end.

直到运行时访问它时才决定类型,即

TBitBucket<Integer>.MyProperty := 2;

【讨论】:

  • (1) 不要粗鲁,但您似乎对术语更加困惑,因为您提到了“变体”,但不要在代码中的任何位置使用任何变体。 (2) 虽然您的方法是有效的,但它可以大大简化,因为您可以完全删除 FVar 类 var 并让 ThrowAway 方法的主体为空。此外,您不需要创建该类的实例,因为您只使用 class 成员。 TBitBucket&lt;Integer&gt;.MyProperty := Test();
  • @AndreasRejbrand - 我认为 Tav 指的是 OP 正在使用变体这一事实。
  • @Dsm:但是 OP 也没有使用变体......
  • 我指的是 OP 的代码似乎希望泛型像变体一样工作,而他们不会。
【解决方案2】:

这是我能想到的最短的解决方案

type TBitBucket = class
  class var ThrowAway: variant;
end;

用法

type test = class
  procedure Test;
end;


implementation

{ test }

procedure test.Test;
begin
  TBitBucket.ThrowAway := 'AString';
  TBitBucket.ThrowAway := 1;
  TBitBucket.ThrowAway := 1.1234;
  TBitBucket.ThrowAway := true;
end;

T值示例

这里是一个使用 TValue 代替 system.RTTI 的示例,允许将对象放入存储桶中

type TBitBucket = class
  class var ThrowAway: Tvalue;
end;

type test = class
  procedure Test;
end;


implementation

{ test }

procedure test.Test;
begin
  TBitBucket.ThrowAway := 'AString';
  TBitBucket.ThrowAway := 1;
  TBitBucket.ThrowAway := 1.1234;
  TBitBucket.ThrowAway := true;
  TBitBucket.ThrowAway := TObject.Create;
end;

【讨论】:

    猜你喜欢
    • 2013-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-14
    相关资源
    最近更新 更多