代码之家  ›  专栏  ›  技术社区  ›  Thomas Flinkow

延迟计算的属性语法差异

  •  0
  • Thomas Flinkow  · 技术社区  · 7 年前

    对于延迟评估的属性,以下两种方法(具有支持字段的属性和具有默认值的属性)之间是否存在任何差异,或者它们是否等效?

    // (1)
    public static class Foo
    {
        private static readonly Lazy<Foo> instance = new Lazy<Foo>();
        public static Foo Instance { get; } = instance.Value;
    }
    
    // (2)
    public static class Foo
    {
        public static Foo Instance { get; } = new Lazy<Foo>().Value;
    }
    

    我想要实现的是一个 Foo 仅在访问时创建 Foo.Instance ,而不是之前,更是如此 如果从未访问,则不应创建任何实例。

    2 回复  |  直到 7 年前
        1
  •  3
  •   Lasse V. Karlsen    7 年前

    嗯,事实上,不,他们没什么不同。

    但是,请注意,这只是一个假设,它们也不起作用,至少不是我希望的那样。

    <property declaration> = <expression>;
    

    声明属性的初始值设定项,该初始值设定项将在所属类型的构造上执行。

    因此:

    private static readonly Lazy<Foo> instance = new Lazy<Foo>();
    public static Foo Instance { get; } = instance.Value;
    

    他一点也不懒惰。它将声明并构造一个 Lazy<Foo>

    第二个具有完全相同的问题,您构造并立即计算懒惰对象,使其成为非懒惰对象。

    正确的方法(这只能通过第一种语法形式实现)是在不使用初始值设定项的情况下使用属性,如下所示:

    private static readonly Lazy<Foo> instance = new Lazy<Foo>();
    public static Foo Instance
    {
        get { return instance.Value; }
    }
    

    或者这个:

    private static readonly Lazy<Foo> instance = new Lazy<Foo>();
    public static Foo Instance
    {
        get => instance.Value;
    }
    

    或者最好是这样:

    private static readonly Lazy<Foo> instance = new Lazy<Foo>();
    public static Foo Instance => instance.Value;
    

    这将声明一个getter 身体 在实际读取属性之前,不会执行该操作。


    TL;博士 总而言之,您给出的两个示例没有什么不同,但它们都(可能)是错误的,您需要更改属性声明来修复它。

        2
  •  0
  •   Hasan Emrah Süngü    7 年前

    除了优秀的 answer 给予 Lasse VÃ¥gsæther Karlsen ,我想进一步推测并假设OP是在单例实现之后。这是一个完全懒惰的方法。

    Approach 1
    public sealed class Singleton {
        //Private ctor of course :P
        private Singleton() {}
        // Instance property to access Singleton Instance
        public static Singleton Instance { get { return Nested.instance; } }
    
        private class Nested {
    
            // Explicit static constructor to tell C# compiler
            // not to mark type as beforefieldinit
            static Nested() { }
    
            internal static readonly Singleton instance = new Singleton();
        }
    }
    
    Approach 2
    public sealed class Singleton
    {
        private static readonly Lazy<Singleton> lazy =
            new Lazy<Singleton>(() => new Singleton());
    
        public static Singleton Instance { get { return lazy.Value; } }
    
        private Singleton()
        {
     }
    }