Подтвердить что ты не робот

Доступ к нестационарному элементу через Lazy <T> или любое выражение лямбда

У меня есть этот код:

public class MyClass
{
    public int X { get; set; }
    public int Y { get; set; }

    private Lazy<int> lazyGetSum = new Lazy<int>(new Func<int>(() => X + Y));
    public int Sum{ get { return lazyGetSum.Value; } }

}

Дает мне эту ошибку:

Инициализатор поля не может ссылаться на нестатические поля, метод или свойство.

Я думаю, что очень разумно обращаться к нестационарному члену через ленивый, как это сделать?

* РЕДАКТИРОВАТЬ *

Принятый ответ решает проблему отлично, но для того, чтобы увидеть подробный и подробный, и всегда - причину проблемы, вы можете прочитать ответ Joh Skeet.

4b9b3361

Ответ 2

Вот упрощенная версия вашей проблемы:

class Foo
{
    int x = 10;
    int y = this.x;
}

И немного менее упрощенный:

class Foo
{
    int x = 10;
    Func<int> y = () => this.x;
}

(this обычно неявно, но я сделал это явным для ясности.)

В первом случае использование this очень очевидно.

Во втором случае это несколько менее очевидно, потому что оно откладывается из-за лямбда-выражения. Это все еще не разрешено, хотя... потому что компилятор попытается построить делегат, который использовал this в качестве цели, например:

class Foo
{
    int x = 10;
    Func<int> y = this.GeneratedMethod;

    private int GeneratedMethod()
    {
        return x;
    }
}

Это запрещено в разделе 10.5.5.2 спецификации С# 5:

Инициализатор переменных для поля экземпляра не может ссылаться на создаваемый экземпляр.

Самое простое исправление - просто поместить инициализацию в тело конструктора, где вы можете обратиться к this. Итак, в вашем коде:

public class MyClass
{
    public int X { get; set; }
    public int Y { get; set; }

    private Lazy<int> lazyGetSum;

    public MyClass()
    {
        lazyGetSum = new Lazy<int>(() => X + Y);
    }

    public int Sum{ get { return lazyGetSum.Value; } }
}

Обратите внимание, что я упростил также выражение лямбда - это очень редко стоит использовать new Func<int>(...).

Ответ 3

Ошибка говорит вам точно, что не так. Вы не можете получить доступ к свойству в полевом инициализаторе.

Предположим, что ваш класс похож:

public class MyClass
{
    public int X { get; set; }
    public int Y { get; set; }

    private Lazy<int> lazyGetSum = new Lazy<int>(new Func<int>(() => 2 + 3));
    public int Sum { get { return lazyGetSum.Value; } }

}

Тогда он скомпилируется без каких-либо проблем. Поскольку в вашем коде вы получаете доступ к свойствам X и Y в инициализации поля. Вы получаете ошибку.

Вы также можете инициализировать их в конструкторе, если хотите:

public class MyClass
{
    public int X { get; set; }
    public int Y { get; set; }

    private Lazy<int> lazyGetSum; 
    public int Sum { get { return lazyGetSum.Value; } }

    public MyClass()
    {
        lazyGetSum = new Lazy<int>(new Func<int>(() => X + Y));
    }

}

Ответ 4

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

public  class MyClass
    {
        public static int X { get; set; }
        public static int Y { get; set; }

        private Lazy<int> lazyGetSum = new Lazy<int>(new Func<int>(() => X + Y));
        public int Sum { get { return lazyGetSum.Value; } }
    }

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

EDIT. Или вы можете определить с помощью своего конструктора без любое определение static.

public MyClass()
    {
        lazyGetSum = new Lazy<int>(new Func<int>(() => X + Y));
    }

с

private Lazy<int> lazyGetSum; 
public int Sum { get { return lazyGetSum.Value; } }

Ответ 5

Если вы хотите использовать нестатический метод. Вы также можете использовать построить альтернативу для Lazy, которая получает параметр Func в .Value, а не в конструкторе Lazy.

Код будет выглядеть так:

public class MyClass
{
    public int X { get; set; }
    public int Y { get; set; }

    private readonly LazyValue<int> lazyGetSum = new LazyValue<int>();
    public int Sum { get { return lazyGetSum.GetValue(() => X + Y); } }
}

Он реализует свойство в свойстве.. Там, где вы могли бы ожидать этого,