代码之家  ›  专栏  ›  技术社区  ›  Zifre

非空引用类型

  •  11
  • Zifre  · 技术社区  · 17 年前

    我正在设计一种语言,我想知道默认情况下使引用类型不可为null,并对可为null的值和引用类型使用“?”是否合理。这有什么问题吗?你会怎么做:

    class Foo {
        Bar? b;
        Bar b2;
        Foo() {
            b.DoSomething(); //valid, but will cause exception
            b2.DoSomething(); //?
        }
    }
    
    8 回复  |  直到 17 年前
        1
  •  16
  •   Adam Wright    17 年前

    我目前的语言设计哲学是,可空性应该是程序员被迫要求的,而不是默认在引用类型上给出的(在这方面,我同意Tony Hoare-谷歌最近关于QCon的演讲)。

    在这个特定的例子中,对于不可空的b2,它甚至不会通过静态检查:保守分析无法保证b2不是空的,因此程序在语义上没有意义。

    我的精神很简单。引用是对某个资源的间接句柄,我们可以遍历它来访问该资源。可为空的引用包括 要么 资源的间接句柄, 或 资源不可用的通知,并且人们永远无法预先确定正在使用哪种语义。这要么会预先进行大量检查(它是空的吗?不是?耶!),要么会产生不可避免的NPE(或等效物)。如今,大多数编程资源并没有受到大规模的资源约束,也没有绑定到一些有限的底层模型——简单地说,空引用就是其中之一。..

    • 困惑:“我还不知道该放什么”。通常也是旧语言的遗留问题,在知道资源是什么之前,你必须声明你的资源名称。
    • 错误:“出错了,这里有一个NULL”。因此,更好的错误报告机制在语言中至关重要

        2
  •  11
  •   Brian    17 年前

        3
  •  9
  •   Daniel Earwicker    17 年前

    Spec#

    我也会把使用它定为非法。可以为空的引用(或任何其他可以解除引用它的东西)上的运算符。你会如何使用它们?你必须先将它们转换为非空值。你会怎么做?通过测试它们是否为null。

    if bool 测试表达式。我会扩展它以接受可以为null的引用变量的名称:

    if (myObj)
    {
        // in this scope, myObj is non-nullable, so can be used
    }
    

    myObj 在真理分支内。

    我会再加一点糖:

    if (SomeMethodReturningANullable() into anotherObj)
    {
        // anotherObj is non-nullable, so can be used
    }
    

    这只是给出了名字 anotherObj 到左边表达式的结果 into ,因此它可以在有效范围内使用。

    ?: 操作员。

    string message = GetMessage() into m ? m : "No message available"; 
    

    请注意 string message

    然后,对于用值替换null的常见情况,可能需要一点糖:

    string message = GetMessage() or "No message available";
    

    or 将仅有效地应用于左侧的可空类型和右侧的不可空类型。

    IDisposable.Dispose ~Destructor 语法将用于增强 Dispose ,与C++/CLI完全相同。)

    Spec#有另一个与非空值相关的语法扩展,原因是在构造过程中确保非空值正确初始化的问题:

    class SpecSharpExampleClass
    {
        private string! _nonNullableExampleField;
    
        public SpecSharpExampleClass(string s)
            : _nonNullableExampleField(s) 
        {
    
        }
    }
    

    换句话说,您必须以与调用其他构造函数相同的方式初始化字段 base 或 this

        4
  •  4
  •   Brian Agnew    17 年前

    看看 Elvis operator Java 7的提案。这做了类似的事情,因为它将空检查和方法分派封装在一个运算符中,如果对象为空,则具有指定的返回值。因此:

    String s = mayBeNull?.toString() ?: "null";
    

    检查字符串s是否为null,如果是,则返回字符串“null”,如果不是,则返回该字符串的值。思考的食物,也许吧。

        5
  •  3
  •   finnw    17 年前

    其他语言中类似功能的几个例子:

    还有 Nullable<T> (来自C#),但这不是一个很好的例子,因为引用与值类型的处理方式不同。

    b?->DoSomething();
    

    b 只有当它不为空时。

        6
  •  0
  •   Armen Michaeli    14 年前

    将可空性作为配置设置,可执行 代码。这样,您将允许默认情况下喜欢可以为null的对象的人在他们的源代码中享受它们,而允许那些希望默认情况下所有对象都不为null的人也这样做。此外,提供关键字或其他工具,明确标记哪些对象和类型的声明可以为空,哪些不能为空,类似于 nullable 和 not-nullable ,以覆盖全局默认值。

    例如

    /// "translation unit 1"
    
    #set nullable
    { /// Scope of default override, making all declarations within the scope nullable implicitly
         Bar bar; /// Can be null
         non-null Foo foo; /// Overriden, cannot be null
         nullable FooBar foobar; /// Overriden, can be null, even without the scope definition above 
    }
    
    /// Same style for opposite
    
    /// ...
    
    /// Top-bottom, until reset by scoped-setting or simply reset to another value
    #set nullable;
    
    /// Nullable types implicitly
    
    #clear nullable;
    
    /// Can also use '#set nullable = false' or '#set not-nullable = true'. Ugly, but human mind is a very original, mhm, thing.
    

    许多人认为,给每个人他们想要的东西是不可能的,但如果你正在设计一种新语言,尝试新事物。Tony Hoare介绍了 null 1965年,因为他无法抗拒(他自己的话),从那以后我们就为此付出了代价(同样,他自己的话说,这个人对此感到后悔)。重点是,聪明、有经验的人犯的错误会让我们其他人付出代价,不要把这个页面上的任何人的建议当作唯一的真理,包括我的。评估并思考它。

    空值 可能是 我没有经验,但我知道我的哪些对象不会从可以为null中受益。

        7
  •  -3
  •   Lennaert    17 年前

    C# did it .

    是的,这是自芭芭拉和斯蒂芬以来语言方面最大的进步 invented types in 1974. :

    芭芭拉·利斯科夫
    麻省理工学院
    MAC项目
    剑桥


    剑桥系统集团
    IBM系统开发部
    剑桥

    动机 包含适合其问题领域的原语或抽象。 专注于解决他的问题,由此产生的程序将是 结果更可靠。显然,这是一个值得追求的目标。 推进其语言使用者可能提出的所有抽象概念 解决设计者没有预见到的问题 语言中嵌入的抽象是不够的。本文 提出了一种方法,允许内置抽象集 当发现需要新的数据抽象时,可以增强。 描述了这种语言的用法和示例 给出了抽象的定义。