How to initialize a generic variable

How do you initialize a generic variable when creating a new class?

Example:

public class Node<T>{
	private T data;
}

public class NodeData{
	private string exampleString = "example";
}

When I create a new instance of a Node with the type NodeData, data is set to null, but I would like it to be initialized.

I can get round this by writing

aNode = new Node<NodeData>(new NodeData());

and creating a constructor that takes this as an argument but is there not a way to have it initialize the generic type inside the class without passing one i make myself into the constructor ie so I’d just type

aNode = new Node<NodeData>();
// T is any type
public class Node<T>
{
    private T data = default(T);
}

// T is a reference type
public class Node<T> where T: class
{
    private T data = null;
}

// T has a public parameterless constructor
public class Node<T> where T: new()
{
    private T data = new T();
}

// T is Animal or derives from it
public class Node<T> where T: Animal
{
    private T data = new Giraffe();
}

This code compiles fine:

public class Node<T> where T : new()
{
	private T data = new T();
}

public class NodeData
{
	private string exampleString = "example";
}

...
var node = new Node<NodeData>();
3 Likes

OK thanks that’s amazing, however the example I gave is simpler than what I’m doing as I’m actually using a class derived from Node, eg ExtendedNode

I’m getting the error:

The type T' must have a public parameterless constructor in order to use it as parameter T’ in the generic type or method `Node’

I’m not sure whats causing this at the moment as your example works I’ll post my entire code in case it obvious to you. Thanks very much for your help.

using UnityEngine;
using System.Collections;
using System.Collections.ObjectModel;

public class Node<T> where T: new(){
//public class Node<T>{
	
//	private T data;
	//private T data = default(T);	
	private T data = new T();
	private NodeList<T> neighbors = null;
	
	//Constructors
	public Node(){
		Debug.Log(Value);
	}
	
	public Node(T data): this(data, null){
	}
	
	public Node(T data, NodeList<T> neighbors){
		this.data = data;
		this.neighbors = neighbors;
	}
	
	
	public T Value{
		get{return data;}
		set{data = value;}
	}
	
	protected NodeList<T> Neighbors{
		get{return neighbors;}
		set{neighbors = value;}
	}
}
public class NodeList<T>: Collection<Node<T>>{
	
	//Constructors
	public NodeList(): base(){
	}
	
	public NodeList(int initialSize){
		for(int i = 0; i < initialSize; i++){
			base.Items.Add(default(Node<T>));
		}
	}
	
	public Node<T> FindByValue(T value){
		foreach(Node<T> node in Items){
			if(node.Value.Equals(value)){
				return node;
			}
		}
		return null;
	}
}
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class GraphNode<T>: Node<T> where T: new(){
//public class GraphNode<T>: Node<T> {
	
	private List<int> costs;
	
	public Rect 			windowRect = new Rect(20, 60, 50, 20);		//Size and position of window
	public Rect				finalLayoutRect;							//Stores the final size of the window after the layout has been completed	

	public GraphNode(): base(){
	}
	
	public GraphNode(T value): base(value){	
	}
	
	public GraphNode(T value, NodeList<T> neighbors): base(value, neighbors){
	}
	
	new public NodeList<T> Neighbors{
		
		get{
			if(base.Neighbors == null){
				base.Neighbors = new NodeList<T>();
			}
			return base.Neighbors;
		}
	}
	
	public List<int> Costs{
		
		get{
			if(costs == null){
				costs = new List<int>();
			}
			return costs;
		}
	}	
	
}
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class Graph<T>: IEnumerable<T> {

	private NodeList<T> nodeSet;
		
	public Graph(): this(null){		
	}
	
	public Graph(NodeList<T> nodeSet){
				
		if(nodeSet == null){
			this.nodeSet = new NodeList<T>();
		}else{
			this.nodeSet = nodeSet;
		}
	}
	
	public void Clear(){
		nodeSet = new NodeList<T>();	
	}
	
	public void AddNode(){
		nodeSet.Add(new GraphNode<T>());
	}
	
	public NodeList<T> Nodes{
		
		get{
			return nodeSet;	
		}
	}

	public IEnumerator<T> GetEnumerator(){
		
		foreach (GraphNode<T> gnode in nodeSet){
			yield return gnode.Value;
		}
		
	}	
	
    IEnumerator IEnumerable.GetEnumerator()
    {
         return GetEnumerator();
    }	
	
	public int Count{
		get {return nodeSet.Count;}	
	}
	
	
}

If you add the new() type constraint to all your Ts, all the compile errors will be gone.

public class Node<T> where T : new()
...
public class NodeList<T> : Collection<Node<T>> where T : new()
...
public class GraphNode<T> : Node<T> where T : new()
...
public class Graph<T> : IEnumerable<T> where T : new()
...

OK thanks I’ll try this out tomorrow

Thanks very much that worked. I then discovered that Unity can’t serialize generic classes and everything I’d written was useless. But thanks very much all the same.

Why not serialize it yourself?

Use a TextAsset and a JSON serializer / deserializer. I use JsonFX