uninitialized field of abstract class not null

Hi,
i hope i got the terms right in the description (i’m a hobbyist programmer).
I have something like this (shortened):

abstract class Spell {
    int ID{get;}
    string Name{get;}
}

and

class Player {
    Spell[] spells = new Spell[10]
    Spell activeSpell;
}

The problem is, that when i check

if (activeSpell != null) {executeThings();}

it’s always not null.
and “executeThings()” even goes through functions in the abstract base class.
The array has the same problem (spells != null → true).
On top of everything Unity crashes consistently.
What did i do wrong?

now i know, that its always accessing the abstract base class where some properties are abviously not implemented, that makes unity crash.
But i expect “Spell activeSpell;” to be null not an instance of the abstract base class.
Why is it not the case?

or am i misunderstanding something?

maybe it’s related to this

?

is it a unity bug, or me not understanding c# ?

help or tips are appreciated.

This is correct, an abstract class can not be instantiated.

From MSDN:

So it is behaving like it should and according to the framework. If you marked the class as public or some other accessor you would be fine.

thank you for your reply.
The problem is, for now i never assign something to “activeSpell”,
i just declare and check it.
Shouldn’t it be null then?
it behaves as if it holds an instance of the base class.

edit: i rewrote it to use an interface instead and this does work as expected.

Did you try declaring activeSpell as null?

Spell activeSpell = null;

hi,
yes i already tested that, but it made no difference.
Though, i thought that uninitialized object fields are null by default.

And they are. Strictly speaking, variables of type T left uninitialized are automatically initialized with the value default(T), which is null for all the reference types.

What you do here is:

  1. You declare a field of type Spell[ ] (a reference to an array of references to spells).

  2. Create an actual array of 10 references to spells and assign its reference to the field. You create no spells here, just an array of 10 uninitialized references to spells - all the array elements are null, until you fill them with something useful - with references to instances of any non-abstract class derived from Spell (not instances of Spell itself because it is abstract).

  3. Declare a field of type Spell (a reference to a Spell instance) and leave the field uninitialized, so it is null too.

It shouldn’t. If it does, the problem is likely somewhere else, NOT inside the code you’ve provided.

If activeSpell is not null and you don’t know why, you may declare it as a property that writes to the console every time it’s being changed:

Spell _activeSpell;
Spell activeSpell
{
    get
    {
        return _activeSpell;
    }
    set
    {
        _activeSpell = value;
        Debug.Log("activeSpell just has been changed");
    }
}

thank you.
I did the test you mentioned but it turned out as expected.
No writing to the property happened but it’s not null;

Even the array is filled with ‘not null’ things.

I already know the part with the reference types, but thanks for refreshing my knowledge.

i assume it has something to do with the abstract class, maybe something i don’t know about them yet.
But i can’t figure out what.

edit: here’s the Spell class:

using UnityEngine;
using System.Collections;

namespace Tarugo
{
	public enum SpellState{
		INVALID=0,
		PRECAST,
		WHILECASTING,
		ENDCAST
	}
	
	[System.Serializable]
	public abstract class Spell:ISpell {
		public abstract int ID {get;set;}
		public abstract string Name {get;set;}
		public abstract Texture2D Icon {get;set;}
		public SpellState state;
		public PlayerScript caster;
		public Vector3 position;
				
		public void Setup(PlayerScript player) {
			caster = player;
			state = SpellState.PRECAST;
		}
		
		public void Cast() {
			if (state == SpellState.PRECAST) {
				PreCast();
			} else
			if (state == SpellState.WHILECASTING) {
				WhileCasting();
			} else
			if (state == SpellState.ENDCAST) {
				EndCast();
				state = SpellState.INVALID;
			}
			if (state == SpellState.INVALID) {
				caster.activeSpell = null;
			}
		}
		
		public abstract void PreCast();
		
		public abstract void WhileCasting();
		
		public abstract void EndCast();
	}
}

I expect that [System.Serializable] is the cause. It is handled differently in Unity compared to .NET in general. I expect this produces as a side effect this weird behaviour. (I am just guessing)

Oh wow… You’re absolutely right!

That indeed was the cause. Now, it works as intended.

Thank you very much.

Do you plan to submit a bug report?

Ah, yes. Doing it now.