22

Is it somehow possible for properties to reference each other during the creation of a dynamic object an anonymously-typed object (i.e. inside the object initializer)? My simplified example below needs to reuse the Age property without making a second heavy call to GetAgeFromSomewhere(). Of course it doesn't work. Any suggestion on how to accomplish this?

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

Is something like this possible or not possible with dynamic objects anonymously-typed object initializers?

7
  • 1
    Assign the result of GetAgeFromSomewhere to a variable in a separate statement beforehand. Commented Apr 18, 2015 at 15:09
  • This probelm also is not directly related to dynamic types but initializers. Commented Apr 18, 2015 at 15:10
  • 2
    @CSharpie Using a statically declared type, the OP could have just made IsLegal a derivative property: public bool IsLegal { get { return Age > 18; } } Commented Apr 18, 2015 at 15:12
  • Aware of creating creating a variable for the value, but I want to avoid creating a dozen variables in the real scenario. Any other ideas? Commented Apr 18, 2015 at 15:14
  • 1
    What is your "real scenario"? You may want to explain in your question when / why you would need this Commented Apr 18, 2015 at 15:19

5 Answers 5

15

Unfortunately it's not possible, even with explicitly typed objects. This is because of the way object initializers work. For example:

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

Yields this compiler error at "IsLegal":

Error 1 A field initializer cannot reference the non-static field, method, or property 'MyClass.Age' ...

Field initializer can't reference other non-static fields, and since anonymous types don't create static fields, you can't use the value of one field to initialize another. The only way around this, is to declare the variables outside the anonymous type and use them inside the initializer.

int age = GetAgeFromSomewhere(id);
var profile = new {
  Age = age,
  IsLegal = age > 18
};
Sign up to request clarification or add additional context in comments.

Comments

3

Don't complicate thing, keep it simple

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

4 Comments

thanks but looking for another solution if possible without creating a dozen variables in my real scenario
@user3199179, Then create a normal class and declare derivative properties.
I'm asking about dynamic objects
Disagree with the claim that is it simpler than the question's example.
3

What you want is not possible within object intializers. You cannot read properties of the object being initialized. (It does not matter, whether the type is anonymous or not.)

Instead, Create a class

public class Profile
{
    public Profile(int id)
    {
        Age = GetAgeFromSomewhere(id);
    }

    public int Age { get; private set; }
    public int IsLegal { get { return Age > 18; } }
}

Or getting the age the lazy way:

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

or using the Lazy<T> class (starting with 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; } }
}

Call it like this

var profile = new Profile(id);

3 Comments

Since you mention the word "lazy" in your second code block, why not simplify your code using Lazy<int>? private readonly Lazy<int> age = new Lazy<int>(() => GetAgeFromSomewhere(_id)); public int Age { get { return age.Value; } }.
I added a statement on object initializers and anonymous types, as well as a usage example of Lazy<T>. Note, C# has a keyword dynamic for the declaration of dynamic objects and using this term in another context can be confusing. Here, you are talking about anonymous types new { ... }.
Note that a type created with new { ... } is anonymous, i.e. it has no public name (it has an internal name known by the compiler so); however, it is created at compile time (not at run time) and is therefore static, not dynamic. Note also that an object created this way is strongly typed, i.e. it is known to have this very anonymous type at compile time and each one of the properties of the type are statically typed as well. (If you assign an expression of type dynamic to one of its properties, this property will be statically typed as dynamic!)
0

If you don't want to have unnecessary variable, I suggest you use the current object instead :

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

profile.IsLegal = profile.Age > 18;

Comments

0

You can add an additional variable and assign the value inline:

int age; // note: you should NOT set an initial value
var profile = new {
  Age = age = GetAgeFromSomewhere(id),
  IsLegal = (age>18)
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.