Лениво оцениваемая разница в синтаксисе свойства - PullRequest
0 голосов
/ 08 февраля 2019

Существуют ли различия между следующими двумя подходами (свойство с резервным полем и свойство со значением по умолчанию) для лениво оцененного свойства или они эквивалентны?

// (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, а не раньше - тем более, когда к Foo.Instance никогда не обращаются, экземпляр создавать никогда не следует.

Ответы [ 2 ]

0 голосов
/ 08 февраля 2019

Помимо превосходного ответа , данного Лассе Вогстер Карлсен , я хотел бы дополнительно поразмышлять и предположить, что OP - после внедрения Singleton.Вот такой ленивый подход.

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()
    {
 }
}
0 голосов
/ 08 февраля 2019

Ну, на самом деле, нет, они не отличаются.

Но, и это только предположение, заметьте, они тоже не работают, по крайней мере, не так, как я надеюсь, вы хотели, чтобы они это делали.

Видите, этот синтаксис:

<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;
}

или, вероятно, лучше, какthis:

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

Это объявит метод получения body , который не будет выполняться до тех пор, пока вы действительно не прочитаете свойство.


TL; DR Подводя итог, приведенные вами два примера не отличаются, но оба они (вероятно) неверны, и вам нужно изменить объявление свойства, чтобы исправить это.

...