在另一个对象引用后初始化对象

时间:2015-08-14 07:01:42

标签: c# object initialization

我有一个2维数组,用于存储棋盘的字段..

private field[,] board = new field[boardsize,boardsize];

..现在当我初始化它们时,我想引用每个字段的邻居,这些字段部分尚未启动。

目前使用这样的解决办法:

for(int x = 0; x < boardsize ; x++)
{
  for(int y = 0; y < boardsize ; y++)
  {
    board[x,y] = new field();
  }
}


for(int x = 0; x < boardsize ; x++)
{
  for(int y = 0; y < boardsize ; y++)
  {
    board[x,y].setNeighbours(x, y, board);
  }
}

这种方法很好,但我很感兴趣,如果可以在初始化之前或之时设置邻居。

setNeighbour - 方法:

setNeighbour(int x, int y, field[,])
{
  if(field[x-1,y] != null)
    this.neighbour[0] = field[x-1,y];
  if(field[x-1,y+1] != null)
    this.neighbour[0] = field[x-1,y+1];
  if(field[x,y+1] != null)
    this.neighbour[0] = field[x,y+1];
  if(field[x+1,y+1] != null)
    this.neighbour[0] = field[x+1,y+1];
  if(field[x+1,y] != null)
    this.neighbour[0] = field[x+1,y];
  if(field[x+1,y-1] != null)
    this.neighbour[0] = field[x+1,y-1];
  if(field[x,y-1] != null)
    this.neighbour[0] = field[x,y-1];
  if(field[x-1,y-1] != null)
    this.neighbour[0] = field[x-1,y-1];

}

4 个答案:

答案 0 :(得分:2)

你可以这样做:

private field[,] board = new field[boardsize,boardsize];

for(int x = 0; x < boardsize ; x++)
{
  for(int y = 0; y < boardsize ; y++)
  {
    if(board[x,y] == null)
        board[x,y] = new field();
    board[x,y].setNeighbours(x, y, board);
  }
}

并以相同的方式检查setNeighbours()方法中邻居的初始化:

private void setNeighbours(int x, int y, field[,] board)
{
    //Initialize neighbour if not already initialized
    if(board[x+1,y] == null)
       board[x+1,y] = new field();

    //DO SOMETHING... 
}

答案 1 :(得分:1)

我不相信它可以引用邻居,因为它们尚未创建。但是,您可以将该板作为参数添加到字段的构造函数中,并在以后需要时使用属性查找邻居。

答案 2 :(得分:0)

这是一个经典的问题......可悲的是,C#没有延续......他们可以通过使用Thread来模拟(非常缓慢)...是的,它有点矫枉过正了只是一个编程练习:

public sealed class WaitForReady<T> : IDisposable
{
    public readonly ManualResetEvent mre = new ManualResetEvent(false);

    public T Value
    {
        get
        {
            mre.WaitOne();
            return this.value;
        }
        set
        {
            this.value = value;
            mre.Set();
        }
    }

    private T value;

    #region IDisposable Members

    public void Dispose()
    {
        mre.Dispose();
    }

    #endregion
}

public class Field
{
    public Field[] Neighbours;

    public Field(WaitForReady<Field> me, WaitForReady<Field>[] neighbours)
    {
        me.Value = this;

        Neighbours = new Field[neighbours.Length];

        for (int i = 0; i < neighbours.Length; i++)
        {
            Neighbours[i] = neighbours[i] != null ? neighbours[i].Value : null;
        }
    }
}

public static void Main(string[] args)
{
    int boardsize = 8;
    Field[,] board = new Field[boardsize, boardsize];

    WaitForReady<Field>[,] boardTemp = null;

    try
    {
        boardTemp = new WaitForReady<Field>[boardsize, boardsize];

        var threads = new Thread[boardsize * boardsize];

        for (int i = 0; i < boardsize; i++)
        {
            for (int j = 0; j < boardsize; j++)
            {
                boardTemp[i, j] = new WaitForReady<Field>();
            }
        }

        int k = 0;

        for (int i = 0; i < boardsize; i++)
        {
            for (int j = 0; j < boardsize; j++)
            {
                var neighbours = new WaitForReady<Field>[8];
                neighbours[0] = i > 0 && j > 0 ? boardTemp[i - 1, j - 1] : null;
                neighbours[1] = i > 0 ? boardTemp[i - 1, j] : null;
                neighbours[2] = i > 0 && j + 1 < boardsize ? boardTemp[i - 1, j + 1] : null;
                neighbours[3] = j > 0 ? boardTemp[i, j - 1] : null;
                neighbours[4] = j + 1 < boardsize ? boardTemp[i, j + 1] : null;
                neighbours[5] = i + 1 < boardsize && j > 0 ? boardTemp[i + 1, j - 1] : null;
                neighbours[6] = i + 1 < boardsize ? boardTemp[i + 1, j] : null;
                neighbours[7] = i + 1 < boardsize && j + 1 < boardsize ? boardTemp[i + 1, j + 1] : null;

                int i1 = i, j1 = j;
                threads[k] = new Thread(() => board[i1, j1] = new Field(boardTemp[i1, j1], neighbours));
                threads[k].Start();
                k++;
            }
        }

        // Wait for all the threads
        for (int i = 0; i < threads.Length; i++)
        {
            threads[i].Join();
        }
    }
    finally
    {
        // Dispose the WaitForReady
        if (boardTemp != null)
        {
            for (int i = 0; i < boardsize; i++)
            {
                for (int j = 0; j < boardsize; j++)
                {
                    if (boardTemp[i, j] != null)
                    {
                        boardTemp[i, j].Dispose();
                    }
                }
            }
        }
    }
}

这里的“技巧”是在64个单独的线程中创建Field。首次初始化时,Field向所有人宣布“自己”(通过设置其对应的WaitForReady<>对象),然后它会询问其邻居的this引用。它通过它作为参数接收的WaitForReady<>个对象来完成此操作。 WaitForReady<>是一个“特殊”容器,可以包含单个值(Value)。如果未设置Value,则要求它将使线程等待,直到有人通过set设置值。

对于小尺寸,可以使用递归来构建所有内容以模拟延续。对于64的电路板,通常是可能的。这更快。

public class Field
{
    public Field[] Neighbours;

    public Field(int i, int j, int boardsize, Func<Field>[,] getters)
    {
        Console.WriteLine("Building [{0},{1}]", i, j);
        getters[i, j] = () => this;

        Neighbours = new Field[8];

        Neighbours[0] = i > 0 && j > 0 ? getters[i - 1, j - 1]() : null;
        Neighbours[1] = i > 0 ? getters[i - 1, j]() : null;
        Neighbours[2] = i > 0 && j + 1 < boardsize ? getters[i - 1, j + 1]() : null;
        Neighbours[3] = j > 0 ? getters[i, j - 1]() : null;
        Neighbours[4] = j + 1 < boardsize ? getters[i, j + 1]() : null;
        Neighbours[5] = i + 1 < boardsize && j > 0 ? getters[i + 1, j - 1]() : null;
        Neighbours[6] = i + 1 < boardsize ? getters[i + 1, j]() : null;
        Neighbours[7] = i + 1 < boardsize && j + 1 < boardsize ? getters[i + 1, j + 1]() : null;
        Console.WriteLine("Builded [{0},{1}]", i, j);
    }
}

public static void Main(string[] args)
{
    int boardsize = 8;

    Field[,] board = new Field[boardsize, boardsize];
    Func<Field>[,] getters = new Func<Field>[boardsize, boardsize];

    for (int i = 0; i < boardsize; i++)
    {
        for (int j = 0; j < boardsize; j++)
        {
            int i1 = i, j1 = j;
            getters[i, j] = () => board[i1, j1] = new Field(i1, j1, boardsize, getters);
        }
    }

    for (int i = 0; i < boardsize; i++)
    {
        for (int j = 0; j < boardsize; j++)
        {
            getters[i, j]();
        }
    }
}

答案 3 :(得分:0)

另一种方法是让Fields处理其他字段的创建。 编写所有代码要做的工作要多得多,但应该提高处理器效率。

原来你不能在构造函数中做到这一点,因为你会进入一个无限循环的字段试图互相创建(因为他们还找不到对方)。

我喜欢做积极内联的事情,即使它只在Release模式下产生微小的差别,实际上在调试模式下减慢了代码的速度。在我的机器上,执行10k的时间约为0.1秒。有兴趣知道这是否比@ xanatos的答案更快。当然还有更多的代码:P

using System.Runtime.CompilerServices;

namespace Algorithms
{
    public class Board
    {
        public Field[,] fields = new Field[8, 8];
    }

    public class Field
    {
        // Neighbor positions
        // 701  +1-1 +10  +1+1 
        // 6 2   0-1  00   0+1
        // 543  -1-1 -10, -1+1
        private Field[] neighbors = new Field[8];

        public void FindNeighbors(Board board, int rank, int file)
        {
            if (rank > 0)
            {
                // Not on bottom
                createNeighbor(board, rank - 1, file, 4);

                if (file > 0)
                {
                    // Not in bottom-left corner, so adding it
                    //createNeighbor(board, rank - 1, file, 4);
                    createNeighbor(board, rank - 1, file - 1, 5);
                    createNeighbor(board, rank, file - 1, 6);

                    if (rank < 7)
                    {
                        // Not on top corner, so adding above and left-above
                        createNeighbor(board, rank + 1, file - 1, 7);
                        createNeighbor(board, rank + 1, file, 0);

                        if (file < 7)
                        {
                            // Not in any corder, adding remainder
                            createNeighbor(board, rank, file + 1, 2);
                            createNeighbor(board, rank - 1, file + 1, 3);
                            createNeighbor(board, rank + 1, file + 1, 1);
                        }
                        else
                        {
                            // On the right, the only fields that haven't been added yet are on the right
                        }
                    }
                    else
                    {
                        // on top
                        if (file < 7)
                        {
                            // Not on the left, so add those fields.
                            createNeighbor(board, rank, file + 1, 2);
                            createNeighbor(board, rank - 1, file + 1, 3);
                        }
                        else
                        {
                            // On the top-left, so nothing else to add.
                        }
                    }
                }
                else
                {
                    createNeighbor(board, rank, file + 1, 2);
                    createNeighbor(board, rank - 1, file + 1, 3);

                    if (rank < 7)
                    {
                        createNeighbor(board, rank + 1, file, 0);
                        createNeighbor(board, rank + 1, file + 1, 1);
                    }
                    else
                    {
                        // Top-left corner, nothing to add
                    }
                }
            }
            else
            {
                // Bottom
                createNeighbor(board, rank + 1, file, 0);

                if (file > 0)
                {
                    // Not on left
                    createNeighbor(board, rank, file - 1, 6);
                    createNeighbor(board, rank + 1, file - 1, 7);

                    if (file < 7)
                    {
                        // Not on the right
                        createNeighbor(board, rank + 1, file + 1, 1);
                        createNeighbor(board, rank, file + 1, 2);
                    }
                }
                else
                {
                    // Bottom-left corner
                    createNeighbor(board, rank + 1, file + 1, 1);
                    createNeighbor(board, rank, file + 1, 2);
                }
            }
        }

        // Neighbor positions
        // 701  +1-1 +10  +1+1 
        // 6 2   0-1  00   0+1
        // 543  -1-1 -10, -1+1
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        private void createNeighbor(Board board, int rank, int file, int neighbor)
        {
            var field = board.fields[rank, file];
            if (field == null)
            {
                field = new Field();
                board.fields[rank, file] = field;
                // Start looking for neighbors after their object is initialized.
                field.FindNeighbors(board, rank, file);
            }

            // Always copy a link to the field, even if it already existed
            neighbors[neighbor] = field;
        }
    }
}