Search code examples
c#object-initializers

How to reference another property value in a C# member initializer?


In VB, the following is a valid object initializer in which one member intializer references the value of another member that has previously been initialized.

new MyObject() with {.Property1="x", .Property2 = .Property1 + "y"}

If I try to do the same in C# using

new MyObject() {Property1 = "x", Property2 = Property1 + "y"}

I get the error

The name 'Property1' does not exist in the current context.

It is a little surprising since there is a fair amount of parity between the two languages but perhaps this is one of those few differences.

Is there a way to do this in C#? For those wondering what the specific use case may be, I am constructing a composite object structure using a fairly complex LINQ query.

IEnumerable<Question> query =
(from q in dtQuestions.AsEnumerable()
 join a in dtAnswers.AsEnumerable() on q.Field<int>("question_type_id") equals a.Field<int>("question_type_id") into Group
 select new Question()
 {
     Id = q.Field<int>("question_type_id"),
     SequenceNumber = q.Field<int>("sequence_no"),
     IsChild = q.Field<bool>("isChildQuestion"),
     EktronContentKey = q.Field<string>("ektron_content_key"),
     Text = q.Field<string>("description"),
     QuestionKindId = q.Field<int>("question_kind_type_id"),
     Answers = (from a2 in Group
                select new Answer()
                {
                    Id = a2.Field<int>("answer_type_id"),
                    SequenceNumber = a2.Field<int>("sequence_no"),
                    EktronContentKey = a2.Field<string>("ektron_content_key"),
                    Text = a2.Field<string>("description"),
                    IsSelected = a2.Field<bool>("isSelected"),
                    ImageKey = q.Field<int>("question_type_id") == 2 ? "" : (Id % 2 == 0 ? "heating-gas-modern.png" : "heating-gas-condensing.png"),
                    ChildQuestionIds =
                          (from r in dtAnswerChildQuestions.AsEnumerable()
                           where r.Field<int>("answer_type_id") == Id
                           select r.Field<int>("question_type_id")).ToArray()
                }).ToArray(),
     SelectedAnswerId = QuestionKindId == 1 ?
                            (from Answer a3 in Answers
                             where a3.IsSelected == true
                             select a3.Id).SingleOrDefault() :
                            0,
     SelectedAnswerIds = QuestionKindId == 2 ?
                           (from Answer a4 in Answers
                            where a4.IsSelected == true
                            select a4.id).ToArray() :
                            new int() { }
 }
);

The real problem to address in this is the reference to the Answers property in the LINQ expression used to assign values to SelectedAnswerId and SelectedAnswerIds. I may have to factor those two expressions out into their own standalone assignments.


Solution

  • I wound up having to resolve this by using a secondary for loop. The code was a bit too complicated to do with LET statements.

        IEnumerable<Question> query =
            (from q in dtQuestions.AsEnumerable()
             join a in dtAnswers.AsEnumerable() on q.Field<int>("question_type_id") equals a.Field<int>("question_type_id") into Group
             select new Question()
             {
                 Id = q.Field<int>("question_type_id"),
                 SequenceNumber = q.Field<int>("sequence_no"),
                 IsChild = q.Field<bool>("isChildQuestion"),
                 EktronContentKey = q.Field<string>("ektron_content_key"),
                 Text = q.Field<string>("description"),
                 QuestionKindId = q.Field<int>("question_kind_type_id"),
                 Answers = new AnswerCollection((from a2 in Group
                                                 select new Answer()
                                                 {
                                                     Id = a2.Field<int>("answer_type_id"),
                                                     SequenceNumber = a2.Field<int>("sequence_no"),
                                                     EktronContentKey = a2.Field<string>("ektron_content_key"),
                                                     Text = a2.Field<string>("description"),
                                                     IsSelected = a2.Field<bool>("isSelected"),
                                                     ImageFileId = a2.Field<int?>("file_id"),
                                                     ChildQuestionIds =
                                                           new Collection<int>((from r in dtAnswerChildQuestions.AsEnumerable()
                                                                                where r.Field<int>("answer_type_id") == a2.Field<int>("answer_type_id")
                                                                                select r.Field<int>("question_type_id")).ToList())
                                                 }))
             }
          );
        foreach (var question in query)
        {
            question.SelectedAnswerId = question.QuestionKindId == 1 ?
                                        (from Answer a3 in question.Answers
                                         where a3.IsSelected == true
                                         select a3.Id).SingleOrDefault() :
                                        0;
            question.SelectedAnswerIds = question.QuestionKindId == 2 ?
                                         new Collection<int>((from Answer a4 in question.Answers
                                                              where a4.IsSelected == true
                                                              select a4.Id).ToList()) :
                                         new Collection<int>();
            this.Add(question);
        }