I'm working on very simple Roguelike game (just for myself) and get a question:
As it is not possible to create a cross-class struct-object (entity in the game case) that could be accessible from any class of my program, what to use to create a cross-class object? I was thinking of something like storing all newly created object (enities) in a static object array, but I guess there is more simple solution on this problem.
Question itself: How to create a cross-class accessible object(s) with your own properties?
Thanks everybody, I found what I was searching for.
It seems like you tried passing around a value type (a struct) between different classes and you noticed that when you update the value in one place it doesn't change the value in another place.
That's the basic difference between value types and reference types.
If you are creating the struct yourself you may want to instead define it as a class.
If not, you could wrap all your structs in a class and pass the class around as your state object.
If all you have is simply a list of the same type of struct (like Points), just pass the List itself around. C# collections are implemented as classes.
public class GameState
{
public Point PlayerLocation { get; set; }
public List<Point> BulletPoints { get; set; }
public double Health { get; set; }
}
Now you can create a GameState and pass it around to different classes:
public class Game
{
private GameState _state = new GameState();
private BulletUpdater _bulletUpdater = new BulletUpdater();
public void Update()
{
_bulletUpdater.UpdatePoints(_state);
// Points have now been modified by another class, even though a Point is a struct.
}
}
public class BulletUpdater
{
public void UpdatePoints(GameState state)
{
for (int i = 0; i < state.BulletPoints.Count; i++)
{
Point p = state.BulletPoints[i];
state.BulletPoints[i] = new Point(p.X + 1, p.Y + 1);
}
}
}
Just remember in the above code if I were to write:
Point p = state.BulletPoints[i];
p.X += 1;
p.Y += 1;
That wouldn't affect the original point! When you read a value type from a list or from a class into only copies the value into a local variable. So in order to reflect your changes in the original object stored inside the reference type you need to overwrite it like so:
state.BulletPoints[i] = p;
This same principal is why the following also will not work:
state.PlayerLocation.X += 5; // Doesn't do anything
state.PlayerLocation.Y += 5; // Also doesn't do anything
The compiler would tell you in this case that you are doing something wrong. You are only modifying the returned value of the property, not the backing field itself. You have to write it like so:
state.PlayerLocation = new Point(state.PlayerLocation.X + 5, state.PlayerLocation.Y + 5); // This works!
You can do the following:
Using IoC Framework, like Ninject. You can setup Ninject to create single instance for all usages.
The other option is to use Singleton pattern design pattern
And the third one is to use static property
It sounds like you want to use the Singleton pattern:
http://en.wikipedia.org/wiki/Singleton_pattern
Here is an example of what this would look like in C#:
public class Singleton
{
static Singleton()
{
Instance = new Singleton();
}
public static Singleton Instance { get; private set; }
}
It's possible. What about public and static class?
public static class CrossClassObject
{
public static object MyProperty { get; set; }
public static void MyMethod() {}
}
Of course this class should be placed in the same namespace that other ones.
How to use it?
class OtherClassInTheSameNamespace
{
private void SomeMethod()
{
var localVariable = CrossClassObject.MyProperty; // get 'cross-class' property MyProperty
CrossClassObject.MyMethod(); // execute 'cross-class' method MyMethod()
}
}
No idea what you are trying to achieve... but if you want a list of objects accessible 'cross-class', just make a static class with a list of objects and then when you reference your class from any other class, you will have access to its list of objects. Here is something like that:
public static class ObjectController
{
private static IList<object> existingObjects;
public static IList<object> ExistingObjects
{
get
{
if (existingObjects == null)
{
existingObjects = new List<object>();
}
}
}
}
public class MyObject
{
public MyObject()
{
ObjectController.ExistingObjects.Add(this);
}
public void Delete()
{
ObjectController.ExistingObjects.Remove(this);
}
}
Then you can add stuff like
MyObject newObj = new MyObject();
//// other stuff... This object should now be visible to whatever other class references ObjectController
newObj.Delete();
Related
I have classes as follow one is SuperClass which is inherited by ChildClass and Child1Class
public class SuperClass
{
public new int Superclassprop = 2;
public virtual void play()
{
Console.WriteLine("SuperClass");
}
}
public class ChildClass : SuperClass
{
public new int Childclassprop = 2;
public override void play()
{
Console.WriteLine("ChildClass");
}
}
public class Child1Class : SuperClass
{
public new int Childclassprop = 3;
public override void play()
{
Console.WriteLine("Child1Class");
}
}
Now when i create an object something like below i don't understand what is the difference between these. i had read a huge bunch of blogs related to this but i didn't find any justifiable answer please help me to understand what actually is happening here or suggest me a good blog or article including on SO where i can understand a whole concept behind this why we need this where the actual real time use of these concept?
SuperClass obj = new SuperClass();
SuperClass obj1 = new ChildClass();
I have attached screenshot of watch which is generating on Run-Time why there is a obj1 consisting all properties but i can access only SuperClassprop?
Thanks in advance any help will be really appreciated.
Here is the more practical example of your topic:
using System;
public class Music
{
public virtual string play()
{
return "Play Music";
}
}
public class Drum : Music
{
public override string play()
{
return "Play Drums";
}
}
public class Piano : Music
{
public override string play()
{
return "Play Piano";
}
}
public class PlayMusicService
{
private readonly Music _musicContext;
public PlayMusicService(Music musicContext)
{
this._musicContext = musicContext;
}
public string PlayAlbum()
{
return _musicContext.play();
}
}
public class Program
{
public static void Main()
{
string whatPlayed = "";
Drum drums = new Drum();
PlayMusicService music1 = new PlayMusicService(new Drum());
whatPlayed = music1.PlayAlbum();
Console.WriteLine(whatPlayed);
Piano piano = new Piano();
PlayMusicService music2 = new PlayMusicService(new Piano());
whatPlayed = music2.PlayAlbum();
Console.WriteLine(whatPlayed);
}
}
Output:
Play Drums
Play Piano
i don't understand what is the difference between these.
One of the main differences is the constructor call
SuperClass obj = new SuperClass();
SuperClass obj1 = new ChildClass();
In the case of obj1 the ChildClass constructor is called after the SuperClass constructor and the field and property initialisation is done also for the property Childclassprop
consisting all properties but i can access only SuperClassprop?
The variable obj1 is still of type SuperClassprop so at compile time you are only allowed to see and use those variables that belong to this class. If you want to actually access the variables of ChildClass you will have to cast it to the proper type:
var r = (obj1 as ChildClass).Childclassproput;
why we need this where the actual real time use of these concept?
One scenario that comes to my mind is : it might be that at compile time it is not clear which class has to be instantiated. But this is decided at runtime. But you need already a variable to write the call of the specific play() method. At runtime it will be decided which method is called in the end.
SuperClass obj = new SuperClass();
bool condition = false;
if (condition)
{
obj = new ChildClass();
}
else
{
obj = new ChildClass1();
}
// now just call the method and the proper method will be called
obj.play();
I'm doing a basic game in C#, and I'm running up on a problem I can't solve. Here's the (relevant) code:
public class GameManager
{
public GameMap MainMap;
public EntityManager GameWorld;
public SystemManager GameSystems;
public GameManager()
{
EntityManager GameWorld = new EntityManager();
SystemManager GameSystems = new SystemManager();
GameMap MainMap = new GameMap(61, 41);
}
public void InputHandler(string Trigger)
{
switch (Trigger)
{
case "north":
GameSystems.Move(GameWorld, MainMap, 0, 8);
break;
//etc
}
}
}
public class SystemManager
{
public rkcPosition _position;
public SystemManager()
{
}
public bool Move(EntityManager TargetWorld, GameMap TargetMap, int TargetID, int TargetDirection)
{
rkcPosition _position = TargetWorld.GetPosition(TargetID);
// here, GetPosition returns an instance of rkcPosition
// pulled from a List<rkcPosition> - this seems to be the problem point
}
}
The problem I'm getting is with the part where I try to call GameSystems.Move - it jumps to highlight the last line of the code I included (w/rkcPosition) and gives a null ref exception. (rkcPosition is a class I've not included in this code snippet)
I'm trying to have the Move function perform some changes to values within the GameWorld and MainMap objects. I'm beginning to think I'm doing this all wrong, so...
If I want to run a method on my existing instances "GameWorld" and "GameSystems" from the InputHandler function, how would I do this properly?
Like Sami Kuhmonen said, the problem in your code is that you are constantly passing around and reassigning your objects that are essentially supposed to be global. Not only does this require that you pass them as parameters to anything that would need them, it is also incredibly error-prone (as you have discovered).
Instead of having these objects behave like instance objects, utilize the Singleton design.
What this means is that instead of instance members, these objects are static members that represent a single global object for everything else to access.
public class GameManager
{
public static GameMap MainMap;
public static EntityManager GameWorld;
public static SystemManager GameSystems;
static GameManager()
{
GameWorld = new EntityManager();
GameSystems = new SystemManager();
MainMap = new GameMap(61, 41);
}
//...
}
Now in your other classes, instead of having to worry if you are passing around the correct object, simply reference these singletons from the GameManager.
public class SystemManager
{
public rkcPosition _position;
//...
public bool Move(int TargetID, int TargetDirection)
{
rkcPosition _position = GameManager.MainMap.GetPosition(TargetID);
}
}
You are constantly redefining variables inside methods that override the member variables. As your debugger shows the GameWorld, MainMap etc are null and you're trying to use them. I don't know how it even goes to Move() since the member variable GameSystems will also be null.
Remove the definitions of the variables inside the methods, that way you're actually storing the objects somewhere and not throwing them away immediately after the method is over. For example:
public GameManager()
{
GameWorld = new EntityManager();
GameSystems = new SystemManager();
MainMap = new GameMap(61, 41);
}
I come today with a weird question.
Is there a way where I can use a non static class like static?
I.e:
We have the following classes:
public class Parameters
{
public String LoadType { get; set; }
public Parameters (String inLoadType)
{
LoadType = inLoadType;
}
}
public class MainClass
{
public Parameters Parameters { get; set; }
public MainClass(String inLoadType)
{
Parameters = new Parameters(inLoadType);
}
}
Now we instantiate MainClass, then somewhere in another place that is not the MainClass I would like to access to the LoadType.
It should be threadSafe, also the operation take quite long, that is the reason I cannot simply just use a lock and make it static.
The class where I want to access that variable is static, I thought in a workaround with a static Event in the Parameters class, and whoever call the event would get the value of the instantiated class or something like that.
Any other Ideas about it beside passing as parameter to the static method what I need?
Sounds like stupid question but I just want to know if is possible or not.
Imagine, that you have two Parameters instances
Parameters one = new Parameters("One");
Parameters two = new Parameters("Two");
and then you call:
String result = SomeWeirdBlackMagicCallOfLoadType();
What is the expected result? "One" or "Two"? In order to solve this
problem, you can turn Parameters into singletone (one instance only) and thus the call will be
String result = Parameters.Instance.LoadType;
but I suggest treating static as static when data doesn't depend on instance. In case of long operations, thread safety you can use Lazy<String> which is specially designed for that:
public class Parameters {
private static Lazy<String> s_LoadType = new Lazy<string>(() => {
....
return "bla-bla-bla";
});
public static String LoadType {
get {
return s_LoadType.Value;
}
}
...
}
I have a list I've set up as a property. I want to add to this list from another class but when I run my code tells me I have null reference. However, I can read from the list just fine. It is only when I add to the list does the error show.
What am I doing wrong?
Property Class
public List<string> ownedShips;
void Start()
{
ownedShips = new List<string> ();
}
public List<string> Ships
{
get {return ownedShips;}
set {ownedShips = value;}
}
Adding to the list from another class:
public int shipCost;
public bool purchasedShip;
public string shipName = "test";
TESTPlayerAccount player;
// Use this for initialization
void Start ()
{
player = new TESTPlayerAccount ();
Debug.Log (player.Currency);
}
public void BuyShip()
{
if(player.Currency >= shipCost)
{
player.Ships.Add(shipName);
}
}
You need something like that, I think
class TESTPlayerAccount
{
private List<string> ownedShips;
public TESTPlayerAccount ()
{
ownedShips = new List<string>();
}
public List<string> Ships
{
get {return ownedShips;}
}
}
You need to initialize the field backing the property:
public List<string> ownedShips = new List<string>();
If the contract for the 'Player' class guarantees that 'Start' is called at instantiation, then initializing the backing field is not required. However, it would be good defensive practice to do so even if that's the case.
You seem to be using functions named Start in place of constructors. If you have to have something initialized when a class instance is created, a constructor is the way to go, as it will be called automatically.
public class TESTPlayerAccount
{
private List<string> ownedShips;
public TESTPlayerAccount()
{
ownedShips = new List<string> ();
}
public List<string> Ships
{
get {return ownedShips;}
set {ownedShips = value;}
}
}
Note that a constructor (public TESTPlayerAccount()) was added in place of your Start() function. The constructor is called automatically at object instantiation when instantiating the class as:
TESTPlayerAccount player = new TESTPlayerAccount();
Constructors can also have parameters. Consider the following constructor that could be added to TESTPlayerAccount in addition to the parameterless constructor that already exists (public TESTPlayerAccount()):
public TESTPlayerAccount(string shipToAddAtStart)
{
ownedShips = new List<string> ();
this.Ships.Add("The best ship evor!");
}
With both of these constructors, you have different behavior.
In the parameterless constructor public TESTPlayerAccount() your list is initialized and that's it.
In the second constructor public TESTPlayerAccount(string shipToAddAtStart) you can provide an initial element to add to the list. Granted you probably don't need the second constructor, just throwing it out there to show you can have more than one constructor for a class that takes different parameters and executes different behavior.
You need to initialize your list. You should really do this in a constructor if you want the collection on the call to new. Also C# has auto properties that mean you only need to write:
Public List<string> MyList {get; set;}
Also you ideally want to expose your property as an interface. The .net generic collections gives you:
IEnumerable<T>
ICollection<T>
IList<T>
In your class you can instantiate any of these interfaces as a List but the exposed type is more flexible.
Judging by the comment, I assume you are using Unity.
If it's true, the Start() function is only called for classes that inherit from MonoBehaviour class.
For your custom classes that do not inherit from MonoBehaviour, change your Start() funtion to the default constructor like this:
TESTPlayerAccount:
public List<string> ownedShips;
public TESTPlayerAccount()
{
ownedShips = new List<string> ();
}
public List<string> Ships
{
get {return ownedShips;}
set {ownedShips = value;}
}
I have created a class that needs to alter a variable's value when it is instantiated.
Example:
In my LrgDialogBox class I might have:
public LrgDialogBox(ref oldResult)
{
// bunch of code
UserInput();
}
public UserInput()
{
newResult=false;
}
In my main class I create an object of my LrgDialogBox called lrgDia then I type:
lrgDia = new LrgDialogBox(ref result);
if (result==true) this.exit;
I basically need to know how to make the reference variable "oldResult" private in my LrgDialogBox class, so that any method can alter its value so it can be used in my main class. Hopefully without changing the parameters of my other methods. Please help.
Kris
There isn't any way for you to meaningfully store the reference parameter that is passed in and be able to modify its value later. What you need to do is add in another layer of indirection; create a reference type that holds onto the value that you really care about. Pass around references to that type, and then all of those references are indirectly pointing to a single value.
The implementation of such a wrapper is simple:
public class Wrapper<T>
{
public T Value { get; set; }
}
You can now create a class that accepts a Wrapper<bool> in the constructor, and then modifies the value within that wrapper at a later point in time.
public class Foo
{
private Wrapper<bool> flag;
public Foo(Wrapper<bool> flag)
{
this.flag = flag;
}
public void Bar()
{
flag.Value = false;
}
}
The other option available to you, since you are, in this case, only calling the method from within the constructor, is to simply have your other method return its value, rather than setting a private field. This would be the preferred design:
public class LrgDialogBox
{
public LrgDialogBox(ref bool oldResult)
{
// bunch of code
oldResult = UserInput();
}
public bool UserInput()
{
return false;
}
}
Just use a private variable to work with during the processing.
private bool _newResult;
public LrgDialogBox(ref bool oldResult)
{
// bunch of code
_newResult = oldResult;
UserInput();
oldResult = _newResult;
}
private void UserInput()
{
_newResult = false;
}