对象初始化程序内的属性可以相互引用吗?

时间:2015-04-18 15:06:09

标签: c# properties object-initializers

在创建动态对象一个匿名类型的对象(即在对象初始化程序内)时,属性是否可能以某种方式相互引用?我在下面的简化示例需要重用Age属性,而不需要对GetAgeFromSomewhere()进行第二次大量调用。当然它不起作用。有关如何实现这一目标的任何建议吗?

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

使用动态对象匿名类型对象初始值设定项可能或不可能这样吗?

3 个答案:

答案 0 :(得分:10)

不幸的是,即使使用显式类型的对象,它也是不可能的。这是因为对象初始化器的工作方式。例如:

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

答案 1 :(得分:5)

不要让事情复杂化,保持简单

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

答案 2 :(得分:3)

在对象初始化器中无法实现所需的功能。您无法读取正在初始化的对象的属性。 (无论这种类型是匿名的还是无关紧要。)

相反,创建一个类

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