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