1

I'm working on a project on c#. I'm using templates for class name State, here's the code:

class State<T>
{
   private T state; //so T could be string or Cell
}   

and I want to initialize it with a class named Cell

public class Cell 
{
  int currentRow,currentColumn;
  Char value;

  public Cell()
  {
    this.currentRow = 4;
    this.currentColumn = 7;
    this.value='0';
  } 
}

Now I want a new State<Cell> to be my initial State, saying:

public class Maze
{
  public State<Cell> initialState;        
  public void CreateMaze(string name, int type)  //creating maze
  {     
    Board Maze = new Cell[size, size]; //board is matrix of cells
    currentRow = random.Next(0, size);
    currentCol = random.Next(0, size);
    Maze[currentRow, currentCol].value = '*';
    initialState = State<Maze[currentRow, currentCol]>; 
  }
}

gives me error "using the generic type requires one argument" help..?

Alex Nolasco
  • 18,750
  • 9
  • 86
  • 81
Zohar Argov
  • 143
  • 1
  • 1
  • 11
  • 3
    Generics are parametrized by types (i.e. classes or value types), not by objects (i.e. instances of classes) and values. – TerraPass Mar 25 '16 at 21:38
  • 2
    you're trying to use an object instance as a type parameter, like @TerraPass said. You can't do that – Jonesopolis Mar 25 '16 at 21:39
  • so how do I do that assigning? it's still a State – Zohar Argov Mar 25 '16 at 21:43
  • 1
    Well, I'm not clear what are you trying to do, but try to replace last line with `initialState = State (currentRow, currentCol);` and see how it goes. – Saleem Mar 25 '16 at 22:01

2 Answers2

1
initialState = State<Maze[currentRow, currentCol]>;

This will not fly, since a type parameter (T in State<T>) needs to be a class or other type, not an object or a value.

You have correctly declared the initialState field in your Maze class as State<Cell>. However, because you have declared no constructors in State<T>, the only thing you can do to initialize this field, outside of leaving null as its value, is:

initialState = new State<Cell>();

This line creates a new object of type State<Cell>. The type State<Cell> is created at runtime, based on generic State<T>, you've defined, using a process called "reification" (see this answer for more info). What you get as a result is a type (a class in your case), which is, basically, State<T> with every occurrence of T in its body replaced by Cell.

Since the only thing you have in your State<T> is a single private field, this class (and its instance) is pretty useless.

To make any use of State<T>, you can mark its state field as public. Optionally, you can change it to a property and maybe declare a constructor:

class State<T>
{
    public T state {get;set;}

    public State(T state)
    {
        this.state = state;
    } 
}

Now you can initialize your initialState in Maze like so:

initialState = new State<Cell>(Maze[currentRow, currentCol]);

(As a side note, do avoid naming your variables with a capital letter, since capitalized names are usually used for classes and methods in C#. Look, even StackOverflow's syntax highlighter is confused.)

Having a public property, you can access the Cell instance, you stored in initialState, simply as initialState.state.

Community
  • 1
  • 1
TerraPass
  • 1,562
  • 11
  • 21
1

I think you are confusing C++ with C#.

Unlike templates in C++, you cannot use instances of a type to access a generic type. You must use the name of the type. This means that this line needs some correcting:

initialState = State<Maze[currentRow, currentCol]>;

I can only guess what you want to do here. I guess you want to create a new State<Cell> object, of which the state property is Maze[currentRow, currentCol].

Hopefully, I'm correct.

In C#, every time you need to create a new object, you need to use the new keyword and call the constructor of the type. So you need to do this:

initialState = new State<Cell>();

"But wait! The state field haven't been set yet!" you shouted. Yes, because at the moment, it can't be set as it is a private field. You can either

  • turn that into a property (recommended) or;
  • change it to public.

If you turn it to a property, it will look like this:

public T MyState {
    get; set;
}

You can also make it immutable, dunno whether you want to do that.

public T MyState {
    get;
}

Then, write a constructor that takes a state parameter and assign that to the property:

public State(T state) {
    this.MyState = state;
}

Now you can initialize your State<Cell> like this:

initialState = new State<Cell>(Maze[currentRow, currentCol]);

I think you get the idea by now, basically,

You cannot set a property/field of a generic class simply by putting in an instance of the class in the place where a generic type parameter should go. Instead, you need to set the property/field manually by an assignment statement.

Sweeper
  • 213,210
  • 22
  • 193
  • 313