Сделать переменную обязательной - чтобы избежать NullReferenceException? - PullRequest
1 голос
/ 19 января 2010

[решено] - Моя ошибка была в том, что я не связывал Мир (мир_) с сущностью, так что это было ноль. Спасибо всем за объяснение!


Как вы, возможно, уже знаете, я делаю игровой движок / фреймворк, и я застрял, связывая вещи со ссылками друг на друга.

Пример:

public void Attach(Entity Entity)
{
    entity_ = Entity;
    entity_.world_.renderer_.AddComponent(this);
}

Строка, добавляющая компонент к средству визуализации, завершается с NullObjectException. Моя идея заключалась в том, что это происходит из-за реализации класса (когда объект еще не определен), но такая вещь работала в следующем фрагменте кода:

public TGSGame()
{
    ...
    Renderer = new RenderManager(this);
    ...
}

Эта часть кода также находится внутри реализации класса TGSGame!

Кто-нибудь знает, как мне преодолеть это исключение?

Ответы [ 6 ]

3 голосов
/ 19 января 2010

Вам необходимо проверить entity_, entity_.world_ и entity_.world_.renderer_ - если любой из них null, он взорвется. Если они имеют основополагающее значение для объекта, обычно рекомендуется инициализировать их в конструкторе и ограничить возможность их изменения / возврата к нулю. Например:

public class Entity {
    public World World {get;private set;}
    public Entity(World world) {
        if(world == null) throw new ArgumentNullException("world");
        tihs.World = world;
    }
}

Преимущество этого состоит в том, что совершенно очевидно, где проблема (она будет показана как ArgumentNullException аргумента "world", когда трассировка стека указывает на конструктор World и все, что вызывает это и т. д.)

1 голос
/ 19 января 2010

Возможно, у вас было исключение NullReferenceException? В любом случае, я бы перепроверил, что ни

entity_.world_

ни

entity_.world_.renderer_

не равно нулю. Просто установите точку останова, и вы увидите, что ваш аргумент Entity не полностью инициализирован.

1 голос
/ 19 января 2010

Вы должны убедиться, что "world_" и "renderer_" существуют до вызова Attach.

Вы можете использовать защитный код:

if ((entity_ != null) && (entity_.world_ != null) && (renderer_ != null)) {
   //... your code here...
} else {
   throw new Exception("...");
}

Помимо этого, вам нужно посмотреть, как вы строите свой граф объектов, чтобы убедиться, что эта ситуация не возникает. В этом случае может помочь хорошая комбинация паттернов Factory и Singleton .

1 голос
/ 19 января 2010

Я думаю, что world_ или renderer_ ссылочные члены, которые еще не были инициализированы.Либо это, либо entity_ передается как null.Трудно сказать без дополнительной информации о том, что они собой представляют.

1 голос
/ 19 января 2010

Одна из ссылок в цепочке entity_.world_.renderer_ пуста, что неудивительно, поскольку вы только что создали ее в предыдущей строке. Обратите внимание, что добавление объекта таким образом во внешнюю коллекцию - это странное обращение ответственности - обычно тот, кто контролирует коллекцию, должен получить контроль над тем, кто к ней что-то добавляет.

1 голос
/ 19 января 2010

Ну, оскорбительная строка

entity_.world_.renderer_.AddComponent(this);

, поэтому либо

entity_.world_

это null, либо

entity_.world_.renderer_

это null, либо что-то плохоепроисходит внутри

entity_.world_.renderer_.AddComponent

Трассировка стека поможет нам вывести немного больше, но это ваши виновники.Начните с проверки правильности инициализации entity_.world_ и, если да, правильной инициализации entity_world_.renderer_.

...