使用 C 中的对象初始化语法将内部对象的成员设置为外部对象#

Set inner object's member as outer object using the object initialization syntax in C#

提问人:Amal K 提问时间:4/8/2021 最后编辑:SomeBodyAmal K 更新时间:4/8/2021 访问量:67

问:

上下文

  • 我有一个类型。List<T>Question
  • 类又包含一个 .QuestionList<Answer>
  • 类有一个成员,称为该成员,该成员存储答案所针对的问题。Answerpublic Question Question { get; set; }

我正在使用集合初始化语法将项目添加到列表中,并使用对象初始化来创建一个新的.在执行此操作时,我还使用对象初始化语法(nested)创建新对象。QuestionQuestionAnswer


问题

如何设置内部类的成员以引用封闭对象?我知道创建点,甚至没有完全初始化。但是有没有办法获取外部实例,以便我可以将其设置为内部。QuestionAnswerQuestionAnswerQuestionQuestionAnswer


法典

private List<Question> questions = new()
{
    new Question 
    { 
            Id = 1, 
            Text = "Test Question 1", 
            Difficulty = QuestionDifficulty.Easy, 
            Answers = 
            {
                new Answer { Id = 1, Question = [?] },
                new Answer { Id = 2, Question = [?] }   // What should replace [?] here?
            }
    } 
};
C# 对象初始值设定项集合 初始值设定项

评论

1赞 Enigmativity 4/8/2021
为什么需要这样做?它创建了一个冗余的数据结构,可能导致将来出现错误。计算父级比存储父级更好。

答:

2赞 SomeBody 4/8/2021 #1

这是不可能的。但是,您可以在创建答案后将问题设置为所有答案。在使用集合初始化期间,不要为 question 属性赋值。在构造函数中,执行以下操作:

foreach(var question in questions)
{
    foreach(var answer in question.Answers)
    {
         answer.Question = question;
    }
}
2赞 Sweeper 4/8/2021 #2

你不能在集合/对象初始值设定项中这样做,但我认为你一开始就不应该在那里这样做。手写每个答案的相应问题应该是什么,这是非常容易出错的。有时你也可能忘记这样做。

我建议你为属性添加一个自定义 setter,它也设置了答案的属性:AnswersQuestionQuestion

private List<Answer> answers;
public List<Answer> Answers {
    get => answers;
    set {
        // If you feel like it, you can also set the old answers' questions to null

        answers = value;
        foreach (var answer in answers) {
            answer.Question = this;
        }
    }
}

然后,在对象初始值设定项中,初始化答案列表,而不仅仅是向其添加:

private List<Question> questions = new()
{
    new Question 
    { 
            Id = 1, 
            Text = "Test Question 1", 
            Difficulty = QuestionDifficulty.Easy, 
            Answers = new List<Answer> // <--- here! 
            {
                new Answer { Id = 1 },
                new Answer { Id = 2 }
            }
    } 
};

这编译为如下:

var question = new Question();
...
var list = new List<Answer>();
var answer1 = new Answer();
answer1.Id = 1;
var answer2 = new Answer();
answer2.Id = 2;
list.Add(answer1);
list.Add(answer2);
question.Answers = list;

正如你所看到的,setter 被调用,answers 的属性将被设置。Question

评论

1赞 SomeBody 4/8/2021
好方法!也许甚至可以使用自定义实现来设置属性,当将新问题添加到列表中时。IListQuestion
2赞 Sweeper 4/8/2021
@SomeBody是的,如果你这样做,你就不再需要了(假设在构造函数中初始化),但是 IMO 为此制作自定义列表实现有点矫枉过正:-)new List<Answer>Answers
0赞 Amal K 4/8/2021
这正是我需要的!非常感谢:)
0赞 Amal K 4/8/2021
@SomeBody 这听起来也不错。我实际上有两者的子类,所以我认为自定义也可以足够合理地创建。但现在,我将采用@Sweeper的方法。谢谢:)QuestionAnswerclass AnswerList : IList<Answer>