Могут ли свойства внутри инициализатора объекта ссылаться друг на друга?
возможно ли, чтобы свойства ссылались друг на друга во время создания динамический объект анонимно типизированный объект (т. е. внутри инициализатора объекта)? Мой упрощенный пример ниже должен повторно использовать Age
свойство без второго тяжелого вызова GetAgeFromSomewhere()
. Конечно, это не работает. Есть предложения, как это сделать?
var profile = new {
Age = GetAgeFromSomewhere(id),
IsLegal = (Age>18)
};
что-то вроде этого возможно, или невозможно с динамические объекты анонимно типизированные инициализаторы объектов?
3 ответов
к сожалению, это невозможно, даже с явно типизированными объектами. Это связано с тем, как работают инициализаторы объектов. Например:
public class MyClass
{
public int Age = 10;
public bool IsLegal = Age > 18;
}
дает эту ошибку компилятора в "IsLegal":
Ошибка 1 инициализатор поля не может ссылаться на нестатические поля, метод или свойство MyClass.Возраст"...
инициализатор поля не может ссылаться на другие нестатические поля, и поскольку анонимные типы не создают статического поля, вы не можете использовать значение одного поля для инициализации другого. Единственный способ обойти это-объявить переменные вне анонимного типа и использовать их внутри инициализатора.
int age = GetAgeFromSomewhere(id);
var profile = new {
Age = age,
IsLegal = age > 18
};
Не усложняйте вещь, держите ее простой
//Create a variable
var age = GetAgeFromSomewhere(id);
var profile = new {
Age = age,
IsLegal = age>18
}
то, что вы хотите не возможно в инициализаторов объекта. Невозможно прочитать свойства инициализируемого объекта. (Не имеет значения, является ли тип анонимным или нет.)
вместо этого создайте класс
public class Profile
{
public Profile(int id)
{
Age = GetAgeFromSomewhere(id);
}
public int Age { get; private set; }
public int IsLegal { get { return Age > 18; } }
}
или получение возраста ленивым способом:
public class Profile
{
private readonly int _id;
public Profile(int id)
{
_id = id;
}
private int? _age;
public int Age {
get {
if (_age == null) {
_age = GetAgeFromSomewhere(_id);
}
return _age.Value;
}
}
public int IsLegal { get { return Age > 18; } }
}
или с помощью Lazy<T>
класс (начиная с Framework 4.0):
public class Profile
{
public Profile(int id)
{
// C# captures the `id` in a closure.
_lazyAge = new Lazy<int>(
() => GetAgeFromSomewhere(id)
);
}
private Lazy<int> _lazyAge;
public int Age { get { return _lazyAge.Value; } }
public int IsLegal { get { return Age > 18; } }
}
назовите это так
var profile = new Profile(id);