成员 - 家长意识

时间:2017-05-06 19:13:59

标签: c# matrix collections delegates

我目前正在研究一种用于在维度上(在网格中)表示对象的结构,使得可以基于它们彼此的关系来描述和交互它们。目前它的工作原理如下:

  • Matrix是集合本身。我包含一个类型为T的列表,其中包含正在组织的原始数据
  • T类型的MatrixItem列表,它们是Matrix的成员并存储它们自己的位置以及正在组织的数据
  • 其最大X和Y尺寸
  • 可包含的最大成员数
  • 目前包含的成员数

所以,我的问题出现在试图让所有网格项相互了解,这就是Matrix的整个目的,这是一个成员通过位置相互了解的集合。我最初的想法是在每个项目中放置一个Top,Bottom,Left和Right邻居,并将其邻居存储在每个成员中。但这不起作用,因为它们是单个实例,不会影响原始对象。我的下一个计划是拥有一个更新机制,当一个更新时,其邻居都更新了它们的定义,当网格更新其邻居时,原始内容将更新。但这不起作用,因为它们互相无限地更新,并且堆栈溢出。

下一个计划是将MatrixItem的引用传递给它的所有邻居,然后每个项目可以简单地相互引用。这不起作用,因为我不知道如何使属性成为另一个对象的引用,获取和设置该属性将动态获取或设置另一个对象,这将在实例化时定义。

我最后的希望是让所有的孩子能够在Matrix中触发一个方法,但我需要让孩子们可以使用它。这是代表们的目的,如果是这样,我在这种情况下如何实现它们?

1 个答案:

答案 0 :(得分:0)

有多种方法可以做到这一点。您实际上有一些好的尝试 - 例如,您可以向MatrixItem添加一个属性,其中包含整个Matrix - 它将自动成为引用,因此如果您在任何时候更新列表,则所有其他属性将是已更新 - 但您必须确保使用相同的Matrix列表初始化所有项目:

//your Matrix list is called matrix
for (var i = 0; i < matrix.MaxLength; i++)
    matrix.Add (new MatrixItem (foo, otherProperty, matrix));

另一个可能的解决方案让每个项目知道它的邻居是什么 - 因为邻居也会知道他的邻居,所以你可以递归获得Matrix的所有项目:

var lastMatrixItem = new MatrixItem (foo, otherProperty, null, null);
matrix.add (lastMatrixItem);
for (var i = 1; i < matrix.MaxLength; i++)
{
    var newMatrixItem = new MatrixItem (foo, otherProperty, lastMatrixItem, null);
    lastMatrixItem.followingItem = newMatrixItem;
    matrix.Add (newMatrixItem);
    lastMatrixItem = newMatrixItem;
}

但如果您不熟悉参考资料,这有点令人困惑。

实际上,如您所述,甚至可以更新MatrixItem的所有Matrix知识:

  

我的下一个计划是拥有一个更新机制,当一个更新时,它的neigbours都更新了它们的定义,当网格更新其邻居时,原始内容会更新。

你只需添加警卫。这意味着,您必须检查分配给该属性的值实际上是否与旧值不同,并且只有这样,才更新该属性。然后,如果值是新的,则仅调用其他项的更新程序功能,因此不会导致无限循环。

一个例子:

public class Item
{
    private int _id;
    public Item Child;
    public Item Parent;

    public int Id
    {
        get => _id;
        set
        {
            if (_id == value) //this is the guard
                return;
            _id = value;
            if (Child != null)
                Child.Id = _id;
            if (Parent != null)
                Parent.Id = _id;
        }
    }

    public override string ToString() =>
        $"Id: {Id} child: ({Child?.ToString() ?? "-"})";
}

如果防护不存在,则会发生StackOverflow异常,因为构建了无限循环。通过上面的课程,这是可能的:

This is a use of the class in the interactive

实际上我在交互式中使用了这个类来演示它。

没有守卫就行不通:

This is the use of the Class without the guard in the interactive

(i被标记为错误的原因是,在StackOverflow异常之后,交互式自身重置)