Need to use instance in static and non-static methods - c#

I'm making a little text game. The starting dialogue is in my main (static) method. From there, it sends you to other methods depending on your choices.
Now I think I need to have an instance of my class for this to work.
For example:
Program p = new Program();
if(stuff){
p.room1();
}
else{
p.room2();
}
Within those other methods there are global variables that will change.
So above the main method there is:
public bool hasItem = false;
So room1() would look like,
public void room1(){
if(stuff){
p.hasItem = true;
}
}
I know I'm screwing something up with the main method. Do I declare the instance "p" inside or outside of the main method? I've tried both but get errors both ways.
Edit: I ended up declaring a static "Program" outside of the main method to use elsewhere. Thanks for the help!

First off, you can either create a static Program outside of your main method, or declare a program inside your main method, depending on your architecture.
Second, you don't have to reference your instance from within your instance methods. Just use the field name. like so:
public void room1(){
if(stuff){
hasItem = true;
}
}
you can use this.hasItem if you want to be explicit about it.
Or better yet, make a brand new class to keep your state in. Having instance members in the class with the main method is awkward design.

Related

c# Do I have to specify name for a new class instance?

I'm making a simple game in unity and have a small uncretainity you could help me with:
do I have to name the new instance of a class?
for example:
public class CreateCharacter : MonoBehaviour {
public string charname;
public CreateCharacter (string charname)
{
this.charname = charname;
//does all the stuff needed
}}
I want to run this from another script:
int e = data.Length - 1;
if (e > 0)
{
new CreateCharacter(data[e]);
e--;
}
data is a string array and CreateCharacter will store the new Character object in a list of such objects, so I can accss it later. My question is:
Do I have to write:
CreateCharacter SomeName = new ChreateCharacter
for the code to run? or is simple
new Class (constructor)
enough?
While it is poor practice to new something and not toss it in a variable, that code WILL compile and run just fine. Additionally, is there a reason you have a class called CreateCharacter? Instead of a function that returns an actual character given the data?
You are allowed to call the constructor by itself like you stated. However, do keep in mind that the newly created object will immediately fall out of scope and be deallocated after the constructor is done. So depending on what's included in "// does all the stuff needed", it could -potentially- crash your app (although it would be unlikely).
As stated in other answers, it is a best practice in both readability and functionality to assign the newly created object to a variable, even if only for the scope of that for loop.
It won't cause the program to die using without storing it.
new CreateCharacter(data[e]);
but yes, you want to store it so you can call methods on it like
CreateCharacter char = new CreateCharacter(string);
char.methodName();
Your other option is to put the code you are trying to execute in a static method because it seems that the code you are running in the constructor is not dependent on the instance of the class CreateCharacter.
If you use
new Class (constructor)
it is anonymous object and it does the job. This king of object is used whenever the object is not referenced from other places of your code and its benefit is that you are not supposed to find an appropriate name for that.

Delayed setup in C# constructor

Hello I was wondering how I can setup several things in a constructor, but have it wait until right after the object is created. I am thinking along the lines of my C++ and QT days when I would create a singleshot timer for 0 seconds that would fire my setup method as soon as the object was constructed. Can I do that in C#?
I don't mind doing all the work I do in the constructor just simply seeing if there is a better way.
In C# whole object is created before executing constructor - all fields are initialized with their default or initial values (if any). If you want to delay something, consider using lazy initialization.
I'm not sure what the problem is with just putting your stuff in the constructor is - there is nothing you cant do. Maybe an example of why you would like to do this / what problem you are having, would allow us to give you a more suited answer.
Although if you really need to delay code,
public constructor()
{
Task.Factory.StartNew(()=>
{
Thread.Sleep(...delay...);
//delayed code
});
}
One way to do what you are asking is to have a static method that constructs the desired object:
class MyObject {
private MyObject() {
}
private void Setup() {
// do some configuration here
}
public static MyObject CreateObject() {
MyObject obj = new MyObject();
obj.Setup();
return obj;
}
}
Thus, you never use the class' actual constructor but instead invoke the static method that creates the object and sets it up at the same time. I am not sure why you would want to do this though, since the effect from the point of view of the caller is the same -- you wait until the object is created and its setup is complete to be able to use it.

What is the correct way of stopping an object in a method that was created in another?

I have a form that has a button which creates a new object and calls it's start() method.
The program works fine, however, I now want to create a stop button. I obviously cannot call the object's stop() method as it is elsewhere, but, I just can't think of the correct way of changing my code.
As I write this, the best thing I can think of is to take the MyObject myo = new MyObject("test"); and place MyObject myo; at the top of the class, outside methods and then try to set it from within the class.
What would you do in this situation?
It's all dependent on scope.
If you want the form, at any time, to have visibility to that object, placing it as a private/protected member within the form's object is probably a good route. (make sure it's not null though.
class MyForm
{
private MyObject myobject;
private MyForm(){
// create the object
myobject = new MyObject;
}
private void Start_Click(){
myobject.start();
}
private void Stop_Click(){
myobject.stop();
}
}
If this object is constantly referenced, you could follow a singleton pattern.
If this is something you can re-create based on [an/the] argument(s) passed to the construct, you can re-create it every time it's needed.
That is is exactly what you are supposed to do. Its called creating a member variable.
But make sure you don't call myo.stop() when myo is null!
You are correct. You have to store the object reference some place so that you can call its "stop" method later.

Calling Main( ) from another class

I have a class named TestMaze. I have another class named DisplayHome which has a method called gameOver():
public void gameOver()
{
Console.Write("GAME OVER!");
Console.Write("Play Again? Y/N");
if(char.ToLower(Convert.ToChar(Console.Read())=='y')
//Main()
else
Environment.Exit(1);
}
How can I call the Main method?
PS. they have the same namespace. I just need to know how can I call the Main method again.
You should have a Play() method inside your Main... and GameOver() should call Play() if user enters 'y'.
Refactor your code. Move whatever needs to be called into another function, and call it from both, main, and gameOver.
Assuming Main is a static class method (which I'd imagine it is) you can simply use MyClass.Main(/*relevant args*/) - beware of course that it's going to be a fresh instantiation, it won't share any non-static variable data.
A possibly better solution however would be to put all your code into a separate class which is invoked/instantiated from Main() - your program can then pass a boolean back to the actual executable Main which will be used to decide whether or not to exit or loop.

C# - Determine if class initializaion causes infinite recursion?

I am working on porting a VB6 application to C# (Winforms 3.5) and while doing so I'm trying to break up the functionality into various classes (ie database class, data validation class, string manipulation class).
Right now when I attempt to run the program in Debug mode the program pauses and then crashes with a StackOverFlowException. VS 2008 suggests a infinite recursion cause.
I have been trying to trace what might be causing this recursion and right now my only hypothesis is that class initializations (which I do in the header(?) of each class).
My thought is this:
mainForm initializes classA
classA initializes classB
classB initializes classA
....
Does this make sense or should I be looking elsewhere?
UPDATE1 (a code sample):
mainForm
namespace john
{
public partial class frmLogin : Form
{
stringCustom sc = new sc();
stringCustom
namespace john
{
class stringCustom
{
retrieveValues rv = new retrieveValues();
retrieveValues
namespace john
{
class retrieveValues
{
stringCustom sc = new stringCustom();
9 times out of 10, infinite recursion bugs are caused by bad property accessors:
public class BrokenClass
{
private string name;
public string Name
{
get { return name; }
set { Name = value; } // <--- Whoops
}
}
I've also had it happen when doing major refactorings with method overloads; sometimes you accidentally end up with a method calling itself when it's supposed to call a different overloaded method.
Either way, you should be able to tell by looking at the call stack for the exception and checking for a repeating pattern. If you see one, then your problem is somewhere in that loop.
Edit - well, based on your example code, you definitely have infinite recursion in the initializers. I have no idea what that code is supposed to be doing, but it's never going to terminate. StringCustom immediately creates RetrieveValues which immediately creates another StringCustom, and so on.
This is one reason why circular class dependencies are typically considered a code smell. Whenever you see ClassA depending on ClassB and ClassB depending on ClassA then you should try to refactor; the exception is if ClassB is entirely owned and managed by ClassA (i.e. an inner class), which is clearly not the case here. You need to eliminate one of the dependencies somehow.
Just put a break point in the constructor of each class you initialize. If you keep accessing the same breakpoints over and over again, I would say infinite recursion is the cause.
I would also check the stack to see what is going on.
Yes, you have an infinite recursion going on because you have two classes which create an instance of the other class in their constructors. As soon as you create an instance of one class, it creates an instance of the other class, which creates an instance of the other class, which creates an instance of the other class etc. etc. etc.
You definitely need to refactor this.
Yeah, I think you are likely on the right track. You can sometimes see this easily in the debugger by looking at the call stack on a break point put at the line of code that causes the exception.
Sound like that is the issue. Can you not pass ClassA into the constructor for ClassB?
Well, everybody understands it. Why not suggest some solution then?
Now, I remember this situation. One way is to avoid calling another contructor inside one. So, there would be extra coding. Eg -
class A {
B b;
A() {}
void Init() { b = new B(); }
}
class B {
A a;
B() {}
void Init() { a = new A(); }
}
...
A aObj = new A();
aObj.Init();
...
B bObj = new B();
bObj.Init();
This will remove the recursion. This is, obviously, easiest way. :)

Categories