I am new to c# and use it with unity3D. When I 开发者_运维技巧use the new
keyword to initialize an object it seems to have null in it even though the object is created and the constructor executes:
public class Wire
{
public Wire()
{
System.Console.WriteLine("constructor executed");
System.Console.WriteLine(this);
}
}
Wire wire1 =new Wire();
System.Console.WriteLine(wire1);
The output is:
constructor executed
null null
I need to store the reference in a list but now I can't. How can I solve this problem?
ok the actual code is
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);
}
}
and in the main i have
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");
}
output:
constructor executed
ok its null
That is not possible.
The this
keyword can never be a null
reference, a constructor can never return a null reference, and calling Console.WriteLine
with a null reference doesn't display "null", it displays an empty line, i.e the same as Console.WriteLine(String.Empty)
.
You can get that behaviour if you override the ToString
method to return the string "null"
:
public class Wire {
public Wire() {
System.Console.WriteLine("constructor executed");
System.Console.WriteLine(this);
}
public override string ToString() {
return "null";
}
}
Please Note: The code in the question itself is never what the actual code is (as stated in the comments) leading people down the wrong path (the Wire class should be shown to inherit from MonoBehavior). And the currently accepted answer has nothing to do with what's happening in this case.
The real issue is, the above code inherits from MonoBehavior. In that case, if you instantiate the class with new it will indeed return true
for (this == null)
and false for (this != null)
. Of course you will still be able to access members of this because the object isn't actually null
, it is just the ==
and =!
operators which are overloaded.
What is going on is that in Unity, for any class that inherits from UnityEngine.Object
(or any subclasses, obviously) it is undefined behavior to instantiated the class via new. To create such objects you have to use UnityEngine.Object.CreateInstance
, MonoBehavior.Instantiate
or some such. The overloaded ==
/ =!
operators probably check for some flag that is set by these custom instantiate methods.
As the question stands, it is incomplete.
The this
keyword will never be null because it only has scope inside instance members of a class. If there is an instance, this
is not null, so by definition it can never be null.
When you pass an argument into WriteLine
, it simply calls ToString
on the argument. If you pass an argument such as a class reference, it will print out the type name if not overridden. In your case, it must be overridden in order to return the string literal "null". Passing a null
argument such as:
string s = null;
Console.WriteLine(s);
Simply doesn't print anything.
If you want to store the reference in a list, you don't store a string representation of the reference, you store the reference itself:
List<Wire> wires = new List<Wire>();
wires.Add(new Wire());
Update: C# doesn't have a "normal copy constructor" unless you have implemented one yourself. However, even if you implement one yourself, it creates a different object.
I am not sure why this is happening but when i call : Debug.Log ("LevelColection constructor " + this);
I get the same result: LevelColection constructor null UnityEngine.Debug:Log(Object)
Edit: So the object is not created if you inherit MonoBehaviour. The thing that worked for me was just remove the : MonoBehaviour and it worked like charm. Have a nice day.
精彩评论