gpt4 book ai didi

delphi - 何时销毁选项类型内的对象?

转载 作者:行者123 更新时间:2023-12-03 14:59:16 25 4
gpt4 key购买 nike

我一直在看Option的使用类型。

这意味着转换如下函数:

Customer GetCustomerById(Int32 customerID) {...}

Customer c = GetCustomerById(619);
DoStuff(c.FirstName, c.LastName);

返回一个选项 Maybe类型:

Maybe<Customer> GetCustomerById(Int32 customerID) {...}

在我的非功能语言中,我必须检查返回值是否存在:

Maybe<Customer> c = GetCustomerById(619);

if (c.HasValue)
DoStuff(c.Value.FirstName, c.Value.LastName);

这工作得很好:
  • 你从函数签名中知道它是否可以返回 null (而不是引发异常)
  • 在盲目使用它之前,您会检查返回值

  • 但是没有垃圾收集

    但我不使用 C#、Java 或 C++ 及其 RAII。我在德尔福;具有手动内存管理功能的本地语言。我将继续用类似 C# 的语言展示代码示例。

    通过手动内存管理,我的原始代码:

    Customer c = GetCustomerById(619);
    if (c != nil)
    {
    try
    {
    DoStuff(c.FirstName, c.LastName);
    }
    finally
    {
    c.Free();
    }
    }

    被转换为类似的东西:

    Maybe<Customer> c = GetCustomerById(619);
    if (c.HasValue)
    {
    try
    {
    DoStuff(c.Value.FirstName, c.Value.LastName);
    }
    finally
    {
    c.Value.Free();
    }
    }

    我现在有一个 Maybe<>保持引用是 无效 ;它比 null 更糟糕,因为现在 Maybe认为它有有效的内容,并且内容确实有一个指向内存的指针,但该内存无效。

    我交易了一个可能的 NullReferenceException到随机数据损坏崩溃错误。

    有没有人考虑过这个问题,以及解决它的技术?

    将 .Free 添加到可能

    我想过在结构中添加一个名为 Free 的方法:

    void Free()
    {
    if (this.HasValue())
    {
    _hasValue = false;
    T oldValue = _value;
    _value = null;
    oldValue.Free();
    }
    }

    如果人们称之为它,它确实有效;并知道如何称呼它;知道为什么要调用它;并且知道他们不应该调用什么。

    很多微妙的知识,以避免我仅通过尝试使用选项类型引入的危险错误。

    当对象被包裹在 Maybe<T> 中时,它也会分崩离析。实际上是通过未命名为规范的方法间接销毁的 Free :

    Maybe<ListItem> item = GetTheListItem();
    if item.HasValue then
    begin
    DoStuffWithItem(item.Value);
    item.Value.Delete;
    //item still thinks it's valid, but is not
    item.Value.Selected := False;
    end;

    奖金喋喋不休
    Nullable/ Maybe/ Option type 在处理没有内置非值的类型(例如记录、整数、字符串,其中没有内置非值)时具有优势。

    如果一个函数返回一个不可为空的值,那么如果不使用一些特殊的 就无法传达返回结果的不存在。哨兵值。
    function GetBirthDate(): TDateTime; //returns 0 if there is no birth date
    function GetAge(): Cardinal; //returns 4294967295 if there is no age
    function GetSpouseName: string; //returns empty string if there is no spouse name

    选项 用于避免特殊的哨兵值,并向调用者传达真正发生的事情。
    function GetBirthDate(): Maybe<TDateTime>;
    function GetAge(): Maybe<Integer>;
    function GetSpouseName: Maybe<string>;

    不仅适用于不可为空的类型
    Option类型也流行了一种避免方式 NullReferenceExceptions (或 EAccessViolation 在地址 $00000000)通过分隔 东西没什么 .

    函数返回特殊的,有时是危险的,信号值
    function GetBirthDate(): TDateTime; //returns 0 if there is no birth date
    function GetAge(): Cardinal; //returns 4294967295 if there is no age
    function GetSpouseName: string; //returns empty string if there is no spouse name
    function GetCustomer: TCustomer; //returns nil if there is no customer

    被转换为特殊的、有时是危险的、前哨值是不可能的形式:
    function GetBirthDate(): Maybe<TDateTime>;
    function GetAge(): Maybe<Integer>;
    function GetSpouseName: Maybe<string>;
    function GetCustomer: Maybe<TCustomer>;

    调用者实现函数可以返回 没什么 ,他们必须通过检查存在的箍。对于已经支持的类型是 , Option让我们有机会尝试阻止人们引发 NullReference 异常。

    在函数式编程语言中,它更加健壮;返回类型可以构造为 不可能 返回 nil - 编译器不会允许它。

    在过程编程语言中,我们能做的最好的事情就是锁定 nil ,并使其无法到达。在这个过程中,调用者拥有更健壮的代码。

    有人可能会争辩说“为什么不告诉开发人员永远不要犯错误”:

    :
    customer = GetCustomer();
    Print(customer.FirstName);

    :
    customer = GetCustomer();
    if Assigned(customer)
    Print(customer.FirstName);

    只要好起来。

    问题是我想要 编译器捕获这些错误。我希望一开始就更难发生错误。我想要一个成功的坑。它迫使调用者理解该函数可能会失败。签名本身解释了要做什么,并使处理变得容易。

    在这种情况下,我们隐式返回两个值:
  • 客户
  • 指示客户是否真的在那里的标志

  • 函数式编程语言中的人们已经采用了这个概念,人们正试图将这个概念带回到过程语言中,即你有一种新的类型来传达值是否存在。并试图盲目使用它会产生编译时错误:
    customer = GetCustomer();
    Print(customer.FirstName); //syntax error: Unknown property or method "FirstName"

    奖励阅读

    如果您想了解更多有关尝试使用函数式 Maybe 的信息monad 在过程语言中,您可以咨询有关该主题的更多想法:
  • 甲骨文 Java:Tired of Null Pointer Exceptions? Consider Using Java SE 8's Optional!
  • 德尔福法术:Never return nil? Maybe!
  • Removing Null from C#
  • 最佳答案

    唯一可以保护您免于在您的 Value 上调用任何内容的方法包裹在 Maybe是从 Maybe 中提取值变量清除 Maybe content 并像通常使用任何对象引用一样使用结果。

    就像是:

      TMaybe<T> = record
    strict private
    FValue: T;
    public
    ...
    function ExtractValue: T;
    end;

    function TMaybe<T>.ExtractValue: T;
    begin
    if not _hasValue then raise Exception.Create('Invalid operation, Maybe type has no value');
    Result := FValue;
    _hasValue = false;
    FValue := Default(T);
    end;

    然后你将被迫提取值(value)才能使用它。
    Maybe<ListItem> item = GetTheListItem();
    if item.HasValue then
    begin
    Value := item.ExtractValue;
    DoStuffWithItem(Value);
    Value.Free;
    end;

    关于delphi - 何时销毁选项类型内的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45868414/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com