2015-04-18 3 views
5

Возможно ли, что свойства ссылаются друг на друга во время создания динамического объекта анонимно типизированного объекта (т. Е. Внутри инициализатора объекта)? Мой упрощенный пример ниже требует повторного использования свойства Age, не делая второго тяжелого вызова GetAgeFromSomewhere(). Конечно, это не сработает. Любое предложение о том, как это сделать?Может ли свойства внутри инициализатора объекта ссылаться друг на друга?

var profile = new { 
    Age = GetAgeFromSomewhere(id), 
    IsLegal = (Age>18) 
}; 

ли что-то подобное возможно или не возможно с динамическими объектами анонимно типизированных объектов Инициализаторы?

+1

Назначить результат «GetAgeFromSomewhere» переменной в отдельном заявлении заранее. –

+0

Эта проблема также не связана напрямую с динамическими типами, но инициализаторами. – CSharpie

+2

@CSharpie Используя статически объявленный тип, OP мог бы просто сделать «IsLegal» производным свойством: public bool IsLegal {get {return Age> 18; }} ' –

ответ

6

К сожалению, это невозможно, даже с явно набранными объектами. Это связано с тем, как работают инициализаторы объектов. Например:

public class MyClass 
{ 
    public int Age = 10; 
    public bool IsLegal = Age > 18; 
} 

Урожайность этой ошибки компиляции на «IsLegal»:

Ошибки 1 Поле инициализатор не может ссылаться на нестатическое поле, метод или свойство «MyClass.Age» .. .

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

int age = GetAgeFromSomewhere(id); 
var profile = new { 
    Age = age, 
    IsLegal = age > 18 
}; 
+0

Отличный, информативный ответ. Благодаря! – user3199179

5

Не усложнять вещи, держать его просто

//Create a variable 
var age = GetAgeFromSomewhere(id); 
var profile = new { 
    Age = age, 
    IsLegal = age>18 
} 
+0

спасибо, но, если возможно, вы ищете другое решение без создания дюжины переменных в моем реальном сценарии – user3199179

+2

@ user3199179. Затем создайте нормальный класс и объявите производные свойства. – Satpal

+0

Я спрашиваю о динамических объектах – user3199179

2

То, что вы хотите, не представляется возможным в пределах объекта инициализаторы. Вы не можете читать свойства инициализируемого объекта. (Это не имеет значения, является ли анонимный тип или нет.)

Вместо Создать класс

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); 
+0

Поскольку вы упоминаете слово «ленивый» в своем втором блоке кода, почему бы не упростить код, используя 'Lazy '? 'private readonly Lazy age = new Lazy (() => GetAgeFromSomewhere (_id)); public int Age {get {return age.Value; }} '. – stakx

+1

, пожалуйста, прочитайте вопрос об динамических объектах – user3199179

+1

Я добавил инструкцию по инициализаторам объектов и анонимным типам, а также пример использования «Lazy ». Обратите внимание: на C# есть ключевое слово 'dynamic' для объявления динамических объектов, и использование этого термина в другом контексте может сбить с толку. Здесь вы говорите об анонимных типах 'new {...}'. –

Смежные вопросы