Что заставляет указатель "this" быть нулевым в моем конструкторе? - PullRequest
1 голос
/ 13 сентября 2011

Я новичок в c # и использую его с unity3D. Когда я использую ключевое слово new для инициализации объекта, в нем, похоже, есть ноль, хотя объект создан и конструктор выполняет:

public class Wire
{
  public Wire()
  { 
    System.Console.WriteLine("constructor executed");
    System.Console.WriteLine(this);
  }
}

Wire wire1 =new Wire();
System.Console.WriteLine(wire1);

Вывод:

конструктор выполнен
нуль
null

Мне нужно сохранить ссылку в списке, но сейчас я не могу. Как я могу решить эту проблему?


ок, фактический код

public class SharedResources
{    
    public static Dictionary< GameObject , Wire> dict = 
       new Dictionary<GameObject, Wire>();
    //...
}

public class Wire
{
    public GameObject x = y.y; 
    //y.y is another gameobject so its a normal copy constructer

    public Wire()
    { 
        print("constructor executed"); 
        // print is provided from unity package
        SharedResources.dict.Add( x,this);
    }
}

и в основном у меня есть

Wire wire1 = new Wire();
if ( SharedResources.dict.ContainsKey( wire1.x) )
{
    print("ok"); // it does print that!!
    if ( SharedResources.dict[wire1.x] !=null )
        print("its not null");
    else
        print("its null");
}
* * Тысяча двадцать-одина выход:

конструктор выполнен
ОК
его ноль

Ответы [ 4 ]

3 голосов
/ 24 января 2012

Обратите внимание: Код в самом вопросе никогда не является тем, чем является действительный код (как указано в комментариях), ведущий людей по неверному пути (класс Wire должен быть унаследован от MonoBehavior),И принятый в настоящее время ответ не имеет ничего общего с тем, что происходит в этом случае.

Реальная проблема в том, что приведенный выше код наследуется от MonoBehavior.В этом случае, если вы создадите экземпляр класса с новым, он действительно вернет true для (this == null) и false для (this != null).Конечно, вы все равно сможете получить доступ к членам этого, потому что объект на самом деле не null, это просто перегруженные операторы == и =!.

что в Unity для любого класса, который наследуется от UnityEngine.Object (или для любых подклассов, очевидно), поведение экземпляра класса с помощью new является неопределенным поведением.Для создания таких объектов вы должны использовать UnityEngine.Object.CreateInstance, MonoBehavior.Instantiate или что-то подобное.Перегруженные операторы == / =!, вероятно, проверяют наличие флага, установленного этими пользовательскими методами создания экземпляров.

3 голосов
/ 13 сентября 2011

Это невозможно.

Ключевое слово this никогда не может быть ссылкой null, конструктор никогда не может вернуть нулевую ссылку, а вызов Console.WriteLine с нулевой ссылкой не отображает "ноль", он отображает пустую строку, т.е. такой же как Console.WriteLine(String.Empty).

Вы можете получить такое поведение, если переопределите метод ToString для возврата строки "null":

public class Wire {

  public Wire() {
    System.Console.WriteLine("constructor executed");
    System.Console.WriteLine(this);
  }

  public override string ToString() {
    return "null";
  }

}
2 голосов
/ 13 сентября 2011

Поскольку вопрос стоит, он является неполным.

Ключевое слово this никогда не будет нулевым, поскольку оно имеет область видимости только внутри членов экземпляра класса.Если есть экземпляр, this не является нулевым, поэтому по определению он никогда не может быть нулевым.

Когда вы передаете аргумент в WriteLine, он просто вызывает ToString для аргумента.Если вы передадите аргумент, такой как ссылка на класс, он выведет имя типа, если оно не переопределено.В вашем случае он должен быть переопределен, чтобы возвращать строковый литерал "null".Передав аргумент null, такой как:

string s = null;
Console.WriteLine(s);

Просто ничего не печатается.

Если вы хотите сохранить ссылку в списке, вы не сохраните строковое представлениессылки, вы сохраняете саму ссылку:

List<Wire> wires = new List<Wire>();
wires.Add(new Wire());

Обновление: C # не имеет "обычного конструктора копирования", если вы не реализовали его самостоятельно.Однако даже если вы реализуете его самостоятельно, он создает другой объект.

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

Я не уверен, почему это происходит, но когда я звоню: Debug.Log («Конструктор LevelColection» + this);

Я получаю тот же результат: LevelColection конструктор null UnityEngine.Debug: Log (Object)

Edit: Таким образом, объект не создается, если вы наследуете MonoBehaviour. То, что работало для меня, было просто удалить: MonoBehaviour, и это работало как шарм Хорошего дня.

...