So I'm working with two files: Simulator and Environment. In the environment file, I have a member variable called "Entities". It is defined there and it has constructor and a get-set function. My Simulator class has that Environment class included in its code; with a constructor and a set-get function for it.
Now I am trying to make the Environment class to work within the Simulator class. The code I have right now is supposed to include the environment member variable "Entities" in a for loop code I wrote inside my Simulator class.
The error I'm receiving is that the variable member doesn't exist in the current context. However I want to let the computer know that the member variable is from the Environment class. How can I fix this error? I'm using C#.
This is the code I'm having problem with:
the run() method, from my simulator class
public void run()
{
for (int i = 0; i < 50 && entities.Count > 1; i++)
{
entities.RemoveAll(m => !m.IsAlive());
step(i);
}
}
Here is the environment class.
#region ENVIRONMENT CLASS
//__________________//
// ENVIRONMENT //
//__________________//
public abstract class ENVIRONMENT
{
private List<ENTITY> entities;
public ENVIRONMENT()
{
entities = new List<ENTITY>();
}
public void AddEntity(ENTITY e)
{
entities = new List<ENTITY>();
entities.Add(e);
Random rand = new Random();
foreach (ENTITY element in entities)
{
int locX = rand.Next(0, 9);
int locY = rand.Next(0, 9);
element.X = locX;
element.Y = locY;
//element.LocalPoint.X = locX;
//element.LocalPoint.Y = locY;
}
}
public ICollection<ENTITY> Population
{
get { return entities; }
}
}
EDIT: Earlier I gave another name for Entities and that was List, so I changed it.
I don't see a field named LIST, but I do see a field named entities, of type LIST<ENTITY>.
Add an internal or public get property accessor for your entities variable, and initialize entities to an empty list upon class instantiation.
Also, why are all of your class names (apparently) fully UPPERCASE?
public abstract class ENVIRONMENT
{
private List<ENTITY> entities = new List<ENTITY>();
public List<ENTITY> Entities
{
get { return entities; }
}
...
}
Related
I am developing a little console game where you go through a dungeon. I'm trying to make a potion system for it, the idea is that when you use a potion, it changes a specific stat of the player.
The stats of the player are stored in a static class called Stats. I want to create different potions from the same class, and change the stat the potion acts on using its constructor method. The way I want this to work is that, when a new potion instance is created, I pass to the constructor a reference to the stat variable, and the constructor will store that reference in a variable, to use it when the potion is used.
I tried using delegates with getters and setters, but it didn't work because they only work with functions. I can solve this problem making a potion id system, or learning to proper use pointers, but I prefer to use only safe code.
My question is: There is a way in c# to store a reference to a variable in another variable?
The Stats class:
static class Stats{
public static int health = 10,
strenght = 5,
defense = 20;
}
The potion class:
class Potion {
int statRef; //This is the "reference holder" variable I was asking about.
int magnitude;
public Potion(ref int stat, int _magnitude)
{
magnitude = _magnitude;
statRef = stat; //Here I want to save the reference to the stat to the "reference holder"
}
public void UsePotion()
{
statRef += magnitude; //Here I want to change the referenced variable's value.
}
}
The main program:
class Program{
static class Main(string[] args)
{
Potion lifePotion = new Potion(Stats.life, 5);
Potion strenghtPotion = new Potion(Stats.strenght, 5);
Potion defensePotion = new Potion(Stats.defense, 10);
lifePotion.UsePotion();
strenghtPotion.UsePotion();
defensePotion.UsePotion();
Console.WriteLine(Stats.health);
Console.WriteLine(Stats.strenght);
Console.WriteLine(Stats.defense);
}
}
Note that a class is a reference type. So, variables of a class type automatically contain references and you can assign the same reference to another variable. You can only create an object (i.e., an instance of a class) if the class is not static. Then you can assign it to a variable.
The fields or properties must not be static. Non static members are called instance members. Each instance (object) has its own copy of the fields and properties that must be accessed through a variable name. Static members, in contrast, are shared among all objects of this type and must be accesses through the class name.
Stats stats1 = new Stats();
Stats stats2 = stats1;
now both variables reference the same Stats. If you make the change
stats1.health = 5;
then stats2.health is also 5 since both reference the same object. But of course, you can create independent Stats objects:
Stats stats1 = new Stats();
Stats stats2 = new Stats();
Now changes to stats1 do not affect stats2.
Note that an important idea of Object-Oriented Programming (OOP) is that objects should hide their internal state, i.e., their fields. From outside the state should only be accessible through methods. These methods ensure that the state is manipulated in an adequate manner. E.g., it could be ensured that the health stays within a valid range.
Properties are specialized methods allowing to manipulate the state of fields. They usually consist of a pair of get and set methods and can be accessed like a field.
Example:
class Stats
{
private int _health = 10;
public int Health
{
get { // called when reading the value: int h = stats1.Health;
return _health;
}
set { // called when setting the value: stats1.Health = 5;
if (value < 0) {
_health = 0;
} else if (value > 100) {
_health = 100;
} else {
_health = value;
}
}
}
}
If a property has no such logic, you can use an auto implemented property. It automatically creates an invisible backing field (like _health) and returns and sets its value.
public int Health { get; set; }
Let us put the things together. Simple example of Stats class:
class Stats
{
public int Health { get; set; } = 10;
public int Strength { get; set; } = 5;
public int Defense { get; set; } = 20;
}
Now you can reference a Stats object in the Potion class.
Because you want to have different kinds of potions, you can use inheritance (another important concept of OOP) to achieve this.
You can declare an abstract base class, i.e., a class that cannot be instantiated and can itself contain abstract members, i.e., members that have still to be defined in derived classes.
abstract class Potion
{
// This is the "reference holder" variable you were asking about.
protected Stats _stats;
// Protected means private and visible to derived classes.
protected int _magnitude;
public Potion(Stats stats, int magnitude)
{
_stats = stats; // Save the reference to the stat to the "reference holder"
_magnitude = magnitude;
}
public abstract void UsePotion();
}
Now the derived LifePotion class as an example
class LifePotion : Potion // Inherits Potion.
{
public LifePotion(Stats stats, int magnitude)
: base(stats, magnitude) // Calls the base constructor.
{
}
public override void UsePotion()
{
_stats.Health += _magnitude; // Change a property of the referenced variable.
}
}
Repeat the same for StrenghtPotion and DefensePotion classes with UsePotion setting the Strength and Defense properties.
The adapted main program
class Program{
static class Main(string[] args)
{
var stats = new Stats();
Potion lifePotion = new LifePotion(stats, 5);
Potion strenghtPotion = new StrengthPotion(stats, 5);
Potion defensePotion = new DefensePotion(stats, 10);
lifePotion.UsePotion();
strenghtPotion.UsePotion();
defensePotion.UsePotion();
Console.WriteLine(stats.Health);
Console.WriteLine(stats.Strength);
Console.WriteLine(stats.Defense);
}
}
Note that you can override ToString in a class and provide your own implementation. Add this to the Stats class:
public override string ToString()
{
return $"Health = {Health}, Strength = {Strength}, Defense = {Defense}";
}
Then you can print the health like this in the main routine:
Console.WriteLine(stats); // Prints: Health = 15, Strength = 10, Defense = 30
C# is an object-oriented programming language. That means it is designed to use “objects”, or in-memory instances of classes, that are responsible for maintaining their own state. Now you don't have to do this, but the more you stray from this design the less the language supports you, and the more work you have to do yourself.
Your design is not object-oriented. There probably isn't a “stats” that wanders around in your game, statting things. It probably isn't static either. Static classes are for concepts that can't change. For example, Math.Sin is static; its meaning can't change and my Math.Sin is your Math.Sin.
Instead of static Stats wandering around, your game probably has characters or Mooks. So make a class for them:
public class Mook
{
public string Name { get; }
public int Strength { get; private set; }
public Mook(string name, int strength)
{
Name = string.IsNullOrWhiteSpace(name) ? throw new ArgumentNullException(nameof(name)) : name;
Strength = strength;
}
}
Now you can create instances of Mooks:
var player = new Mook("Link", 10);
var monster = new Mook("Orc", 11);
Mooks can do things, like attack or drink potions. Potions can do things, like modifying your strength. Each class is responsible only for its own internal state; you don't have potions changing Mooks, only the Mook themselves can do that. Classes do things that change themselves through methods. If you want a Mook to drink a potion you have to create a method inside your Mook class to do that:
public void Drink(Potion potion)
{
switch (potion.Sipped())
{
case PotionEffect.ModifyStrength:
Strength += potion.Modifier;
break;
}
}
Potions don't decide what happens outside themselves, only the class using the potion does. To track the possible effects of a potion, create an enum:
public enum PotionEffect
{
Nothing,
ModifyStrength
}
Potions are other objects, so you need to create another class. Remember, each class is responsible for maintaining its own state:
public class Potion
{
public PotionEffect Effect { get; }
public int Modifier { get; }
public int Doses { get; private set; }
public Potion(PotionEffect defaultEffect, int modifier, int doses)
{
Effect = defaultEffect;
Modifier = modifier;
Doses = doses;
}
public PotionEffect Sipped()
{
if (Doses <= 0)
return PotionEffect.Nothing;
Doses--;
return Effect;
}
}
Now you can create potions:
var strengthPotion = new Potion(PotionEffect.ModifyStrength, +1, 10);
And have mooks drink them:
player.Drink(strengthPotion);
monster.Drink(strengthPotion);
namespace project1
{
public class testclass
{
int i = 0;
public int foobar()
{
int i = 1;
return i;
}
}
}
Result:
1
I am declaring two times of i variable. Why does c# compiler allowing me this ?
If I will try to declare in same scope then compiler will give me exception so why allowing in nested scope?
This is not a bug
Your field int i in the class declaration can be accessed at any time with this.i so there is no overlap. In fact, this is actually the convention to write (private) field names, parameters and local variables within methods in camelCase. Properties, method names, class names etc. on the other hand are written in PascalCase.
So in your class if you want to access the field i of your class, you can do so by writing this.i. Otherwise you will access the scope designated variable i as long as you are within the if-block.
namespace Project1 // PascalCase here for namespace name
{
public class TestClass // Again PascalCase for class name.
{
int i = 0; // camelCase correct here for field name.
public void Foobar() // PascalCase for method name.
{
if (0 == 0)
{
int i = 0; // camelCase correct here for local variable name.
// Cannot be re-declared until your if-block is finished.
// accessing both elements named 'i'
this.i = i;
}
return;
}
}
}
See Microsoft docs for further reference.
All variables declared in a particular scope have to be unique.
You can reuse some variables depending on their data types, but whether or not you should reuse a variable depends on what you're doing.
Your code can work, but you're declaring i a second time which is incorrect as it already exists with a value of 0.
You need to change its value instead of trying to recreate the variable:
namespace project1
{
public class testclass
{
int i = 0;
public void foobar()
{
if (0 == 0)
{
i = 0;
}
return;
}
}
}
You could also create a new variable:
namespace project1
{
public class testclass
{
int i = 0;
public void foobar()
{
if (0 == 0)
{
int j = 0;
}
return;
}
}
}
I've got the following code:
public class Random
{
public string Name { get; set; }
public bool IsRunning()
{
var running = true;
return running;
}
}
public class Main
{
Random newObject = new Random();
newObject.Name = "Johnny";
var result = newObject.IsRunning();
}
which all exists in the same .cs file in the same namespace. Any time I've created a new project before I've never had to set up anything to use dot notation to access member attributes or methods, but this is saying that I can't use newObject. ANYTHING, and also that "var" is not valid for a keyword. It's a windows forms application like I normally use, but I'm drawing blanks here as why I can't do all these things that I normally use many times in my other programs. What am I missing here?
You're trying to write code directly within the class declaration. A class declaration can only directly contain member declarations. It can't contain arbitrary statements such as newObject.Name = "Johnny" nor can it use var, which is only applicable to local variables. If you put the code in a method, it should be absolutely fine. For example:
public class Main
{
public void DoSomething()
{
Random newObject = new Random();
newObject.Name = "Johnny";
var result = newObject.IsRunning();
}
}
As an aside, I'd strongly recommend against naming your own class Random given that that's also the name of a class within the System namespace.
You cannot use var or assign values to some other object within a class member definition.
You code in public class Main is not within a method.
I guess what you were trying to do is writing a Console app and that needs a
public static void Main()
method
so change your class to e.g.
class Program
{
static void Main(string[] args)
{
Random newObject = new Random();
newObject.Name = "Johnny";
var result = newObject.IsRunning();
}
}
I am sending a few separate messages from an asp.net site to my WCF server.
These messages are coming through individually, and I need the server to pick them up, and 'stitch' them together.
What I am trying to do is put those methods in a global List, then using that list in a different class to do my bidding.
So far I have...
variables.cs
class variables
{
public static List<string> MessageStitches { get; set; }
}
Program.cs
if (!string.IsNullOrEmpty(node))
{
variables.MessageStitches.Add(node);
}
But I am getting this error:
Object reference not set to an instance of an object.
Can anyone see where I am going wrong, and how to fix it?
You have not set the variables.MessageStitches property to be a new list.
You have several options, but the best option for you is almost certainly 1 or 2.
1 - Assign a new list in the constructor of variables. However, as your list is static, this will not actually help you, as you may not have instantiated your variables class, and so your constructor will not have run. You can have a static constructor though:
class variables
{
public static List<string> MessageStitches { get; set; }
// Static constructor
static variables()
{
MessageStitches = new List<string>();
}
}
2 - Don't use auto-properties. Instead, have a backing field for your property, which is assigned a value at initialisation:
public class variables
{
private static List<string> messageStitches = new List<string>();
public static List<string> MessageStitches
{
get
{
return messageStitches;
}
set
{
messageStitches = value;
}
}
3 - Check the list before using to ensure it's not null and, if it is, assign a new list then. Again, this will not be threadsafe, unless you take steps to make it so (e.g. by entering a critical section)
if (!string.IsNullOrEmpty(node))
{
if (variables.MessageStitches == null)
{
variables.MessageStitches = new List<string>();
}
variables.MessageStitches.Add(node);
}
Define a constructor in Variable.cs like:
public variables()
{
MessageStitches = new List<string>();
}
or you can do like this :
variables.MessageStitches = new List<string>();
variables.MessageStitches.Add(node);
I am currently working with classes and constructors. I have sint variable named current that equals 0 inside the constructor. Now when I click the button I am trying to increment property current and then call GetNextTree to display. But when incrementing current++ from button click I receive this error: does not exist in current context. What would be the proper way to increment current then?
public class fruit_trees
{
}
public class ListForTrees
{
public int current;
public fruit_trees GetNextTree()
{
current = 0;
fruit_trees ft = first_tree;
int i = 0;
while (i != current)
{
ft = ft.next_tree;
i++;
}
return ft;
}
}
private void ShowNextItem_Click(object sender, EventArgs e)
{
//Show Last Item
fruit_trees obj = mainlist.GetNextTree();
if (obj == null)
{
labelSpecificTree.Text = "No more trees!";
}
else
{
//error: current does not exist?
current++
labelSpecificTree.Text = obj.next_tree.GetTreeType.ToString();
}
}
The problem is in the scope (encapsulation) where you try to call int current.
From your posted code, int current is defined in class ListForTrees. However you are trying to access it without initializing your object of type ListForTrees.
In addition, you are using mainlist which is also not defined in your posted code. Please, post complete code coverage of items that you use in code.
Your current variable is encapsulated inside your ListForTrees class. Since this variable is an instance variable, you need to create a new instance of ListForTrees in order to access this variable using the instance.variable syntax.
Moreover I believe your class design is quite flawed. I think what you should redesign your class like:
public class FruitTree
{
public static int Current { get; set; }
public FruitTree GetNextTree()
{
//your code here
}
}
And then you can initialize a list of trees in your code