Использование оператора объединения нулей внутри функции более высокого порядка - PullRequest
1 голос
/ 23 марта 2012

Я пытаюсь обернуть голову, возможно ли это.Я догадываюсь, что это не требуется, но требуется подтвердить.

Следующая функция более высокого порядка использует оператор объединения нулей:

    public static Func<T> Coalesce<T>(this Func<T> source)
        where T : class
    {
        T local = default(T); 
        return delegate
        {
            return local ?? (local = source()); 
        }; 
    }

Цель состоит в том, чтобы использовать его внутри свойства, например:

    protected string SomeMember
    {
        get { return Coalesce(() => GetSomeMember())(); }
    }

Если бы все работало как задумано, функция GetSomeMember () была бы вызвана только один раз при первом вызове свойства.После этого сохраненный экземпляр свойства может быть возвращен.(его базовая концепция запоминания / объединения нулей).

Теперь сложная часть заключается в попытке уловить сохраненный экземпляр внутри замыкания, вместо того чтобы использовать закрытое поле.Я знаю, что вы можете хранить состояние SomeMember внутри класса, который содержит SomeMember, но я явно пытаюсь избежать этого просто ради любопытства.Цель состоит в том, чтобы все необходимое оставалось внутри блока get {} (включая , а не , в котором хранится делегат, возвращенный из Coalesce ()).

Поскольку внутренняя возвращаемая функция и внешняя функция вызываются каждый раз при обращении к свойству, возникает проблема.Переменная 'T local' каждый раз переопределяется, и, таким образом, оператор слияния null всегда повторно вызывает GetSomeMember ().

Мысли?

Ответы [ 2 ]

3 голосов
/ 23 марта 2012

Это не сработает так, потому что вы звоните Coalesce() (не очень хорошее имя, кстати) каждый раз, когда вызываете геттер. Вы можете сохранить делегата в поле и использовать его. Но если вы делаете это, гораздо лучше использовать Lazy<T> из фреймворка:

private Lazy<string> m_someMember = new Lazy<string>(GetSomeMember);

protected string SomeMember
{
    get { return m_someMember.Value; }
}
0 голосов
/ 23 марта 2012

Не представляется возможным, так как любое замыкание, которое вы попытаетесь получить внутри геттера, не сможет выжить после этого вызова (так как вы не хотите хранить что-либо на объекте).

...