TypeLoadException без причины (возможно) - PullRequest
0 голосов
/ 01 февраля 2020

Я пытаюсь реализовать структуру данных Quad Tree. Когда я уже закончил с этим и запустил проект, я получил перерыв с сообщением:

System.TypeLoadException
  HResult=0x80131522
  Message= Could not load type: "DataStructures.WorldQuadTree+Node" from "SomeProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null".
  Source=<Cannot evaluate the exception source>
  StackTrace:
<Cannot evaluate the exception stack trace>

Вот мой WorldQuadTree класс:

using System;
using System.Collections.Generic;
using MyMath;

namespace DataStructures
{
    class WorldQuadTree
    {
        public struct Configuration 
        {
            public int nodeCapacity;
            public float width;
            public float length;
        }

        struct Node
        {
            private readonly WorldQuadTree tree;
            private bool isSubdivided;

            public readonly BoundingBox boundary;
            public readonly int index;
            public Heap<Node>.Block subNodes;
            public Heap<WorldObject>.Block content;

            public Node(WorldQuadTree tree, int index, BoundingBox boundary, Heap<WorldObject>.Block content)
            {
                this.tree = tree;
                this.index = index;
                this.boundary = boundary;
                this.content = content;
                this.subNodes = default(Heap<Node>.Block);
                this.isSubdivided = false;
            }

            public bool Contains(Vector3 point)
            {
                return boundary.Contains(point) != ContainmentType.Disjoint;
            }

            public bool Intersects(BoundingBox box)
            {
                return boundary.Intersects(box);
            }

            public bool Insert(WorldObject obj)
            {
                for (byte call = 0; call < 2; call++)
                {
                    if (isSubdivided)
                    {
                        int capacity = subNodes.Capacity;

                        for (int i = 0; i < capacity; i++)
                        {
                            if (subNodes[i].Insert(obj))
                                return true;
                        }

                        return false;
                    }
                    else
                    {
                        int capacity = content.Capacity;

                        for (int i = 0; i < capacity; i++)
                        {
                            if (content[i] is null)
                            {
                                content[i] = obj;
                                return true;
                            }
                            else if (content[i].Equals(obj))
                                return false;
                        }

                        isSubdivided = true;
                        subNodes = tree.Subdivide(index);
                        continue;
                    }
                }

                throw new NotImplementedException("Insertion operation has failed.");
            }

            public bool Remove(WorldObject obj)
            {
                if (isSubdivided)
                {
                    int capacity = subNodes.Capacity;

                    for (int i = 0; i < capacity; i++)
                    {
                        if (subNodes[i].Remove(obj))
                            return true;
                    }
                    return false;
                }
                else
                {
                    int index = content.Remove(obj);
                    return index < 0 ? false : true;
                }
            }

            public int GetResponsibleFor(Vector3 point)
            {
                if (boundary.Contains(point) == ContainmentType.Disjoint)
                    return -1;

                if (isSubdivided)
                {
                    int capacity = subNodes.Capacity;

                    for (int current, i = 0; i < capacity; i++)
                    {
                        current = subNodes[i].GetResponsibleFor(point);
                        if (current >= 0)
                            return current;
                    }

                    return -1;
                }
                else return index;
            }

            public void Query(BoundingBox box, List<WorldObject> results)
            {
                if (Intersects(box) is false)
                    return;

                if (isSubdivided)
                {
                    int capacity = subNodes.Capacity;

                    for (int i = 0; i < capacity; i++)
                        subNodes[i].Query(box, results);
                }
                else
                {
                    int capacity = content.Capacity;

                    for (int i = 0; i < capacity; i++)
                    {
                        if (content[i].BoundingBox.Intersects(box))
                            results.Add(content[i]);
                    }
                }
            }
        }


        private readonly int nodeCapacity;
        private readonly Heap<Node> nodesHeap;
        private readonly Heap<WorldObject> contentHeap;
        private Node root;

        public int Capacity => contentHeap.Capacity;

        public WorldObject this[int index] => contentHeap[index];

        public WorldQuadTree(Configuration config, Heap<WorldObject>.Configuration heapConfig) 
        {
            var boundary = new BoundingBox
            {
                Min = new Vector3(-config.width * 0.5f, 0, -config.length * 0.5f), 
                Max = new Vector3( config.width * 0.5f, 0,  config.length * 0.5f),
            };

            this.nodeCapacity = config.nodeCapacity;
            this.nodesHeap = new Heap<Node>(4, 16);
            this.contentHeap = new Heap<WorldObject>(heapConfig.initialCapacity, heapConfig.growRate);
            this.root = new Node(this, 0, boundary, contentHeap.GetBlock(config.nodeCapacity, out _));
        }

        private Heap<Node>.Block Subdivide(int index) 
        {
            Node node = nodesHeap[index];

            Vector3 center = node.boundary.Center;
            Vector3 thickness = node.boundary.HalfExtents;
            var subNodes = nodesHeap.GetBlock(4, out int pointer);

            // begin configuring sub nodes in the conter-clokwise order.

            // Configure top-right node.
            var boundary = new BoundingBox(center, center + thickness);
            subNodes[0] = new Node(this, pointer, boundary, contentHeap.GetBlock(nodeCapacity, out _));

            // Configure top-left node.
            pointer++;
            thickness.X = -thickness.X;

            boundary = new BoundingBox(center, center + thickness);
            subNodes[1] = new Node(this, pointer, boundary, contentHeap.GetBlock(nodeCapacity, out _));

            // Configure down-left node.
            pointer++;
            thickness.Y = -thickness.Y;

            boundary = new BoundingBox(center, center + thickness);
            subNodes[2] = new Node(this, pointer, boundary, contentHeap.GetBlock(nodeCapacity, out _));

            // Configure down-right node.
            pointer++;
            thickness.X = -thickness.X;

            boundary = new BoundingBox(center, center + thickness);
            subNodes[3] = new Node(this, pointer, boundary, contentHeap.GetBlock(nodeCapacity, out _));

            // delegate parent node content to sub nodes
            int length = node.content.Capacity;

            for (int i = 0; i < length; i++) 
            {
                for (int j = 0; j < 4; j++) 
                {
                    if (subNodes[j].Contains(node.content[i].Position)) 
                    {
                        subNodes[j].Insert(node.content[i]);
                        continue;
                    }
                }
            }

            // free parent node content
            node.content.Free();
            nodesHeap[index] = node;

            return subNodes;
        }

        public bool Insert(WorldObject obj) => root.Insert(obj);
        public bool Remove(WorldObject obj) => root.Remove(obj);
        public void Query(BoundingBox box, List<WorldObject> results) => root.Query(box, results);

        /// <summary>
        /// Updates quad tree according to the object movement.
        /// </summary>
        /// <returns>
        /// Returns false when given object is outside of boundary, otherwise true.
        /// </returns>
        public bool OnObjectMoved(WorldObject obj, Vector3 displacement) 
        {
            int to = root.GetResponsibleFor(obj.Position);
            int from = root.GetResponsibleFor(obj.Position - displacement);

            if (from < 0)
            {
                throw new ArgumentException($"Has not contained object: {obj}, at position: {obj.Position - displacement}.");
            }
            else nodesHeap[from].Remove(obj);

            if (to >= 0)
            {
                nodesHeap[to].Insert(obj);
            }
            else return false;

            return true;
        }

        public void Clear(bool shouldMinimizeMemory = false) 
        {
            if (shouldMinimizeMemory) 
            {
                contentHeap.SetMinimumCapacity(nodeCapacity);
            }

            nodesHeap.Clear();
            contentHeap.Clear();
        }
    }
}

Я знаю, что уже есть популярный: Assembly name should differ from .exe file name. Но я не знаю, как это проверить. Я имею в виду, у меня есть много файлов .dll в моей папке bin/x86/Debug, но ни один из них не имеет такого же имени, как мой файл .exe. Я также думаю, что VS даже не создавал мой основной (проект) .dll файл.

Понятия не имею, что происходит не так ...

Кстати, я использую Visual Studio 2019 с проект запущен на. NET framework 4.

РЕДАКТИРОВАТЬ:

Когда я удаляю этот файл (WorldQuadTree.cs) из моего проекта - все работает нормально, и приложение работает работоспособный. Теперь я знаю, что с моим КОДОМ что-то не так. Тем не менее, я не вижу никаких проблем в моем коде, которые могут вызвать "TypeLoadException". Я пытаюсь переименовать каждый класс, который использовал в нем, но результат был тот же Надеюсь, это поможет вам ... и мне.

1 Ответ

0 голосов
/ 17 февраля 2020

Я решил проблему, хотя я не мог повторить ее в новом пустом проекте.

Но.

Когда я изменил " Block " type from " struct"to" class"System.TypeLoadException прошло; и если я откатил предыдущие изменения, то исключение снова будет выдано.

Даже если я не смог повторить его в новом пустом проекте, оно определенно зависит от Тип блока, являющийся struct .

...