I'm working on a game where I have a class for my character and a class to handle the GUI.
In the character class I have an array of structs which hold data about the character's skills. I'm trying to access this array with the GUI class, to display the info about the skills.
To use one class in another one, I would need to initialize a new instance of it, which resets the values I might have changed in the meantime. Is there any way to pass that array? I can't make it read-only because I still have to change the array. The array is also not being modified in the GUI class.
Also, in the future I'm going to save this data in XML or in a database. Is it a possibility to get the info out of these files every time I need them? Instead of having to work with passing the array on and things like that. Or even calculate everything server side?
Thanks in advance!
Simon.
If you want to have one array for the entire program, simply make the array public static. If you want to have that class be able to access the array inside characters that you pass it, make the array public or make a property for which the get part is public.
If your class is not static (which seems not), you can define the array as a property of the character class and have access to array like: myCharacter.Skills.
If you want to have access to your Entities (character class in your case) in multiple projects, you can implement a multi-layer architecture and define your entities in an isolated class library and reference this class library in any project that should have access to you entities.
It is not good practice to pass data in to a GUI directly, if it can be avoided. I would suggest using the Model-View-Controller pattern or the Model-View-Presenter pattern. If you're using WPF, you should look at Model-View-ViewModel.
Basically, you want a class whose responsibility is to maintain the data (whether it be stored in memory, a database, etc.), the view needs some abstraction from the data, and also a means to format it for presentation/display purposes (Presenter).
Here is a brief overview : http://en.wikipedia.org/wiki/Model-view-presenter
Either your character should be static or you should store a reference to your character (or a List<Character> in your GUI class. Furthermore, it would probably be best not to provide direct access to the list of structs that maintains your character information if you just want to print. Your Character class should provide a method(s) for printing out the character data, i.e. character.printCharacterInfo() which will return a string, or maybe character.getCharacterInfo which will return the struct containing the data for that character which your GUI class can use to do whatever it wants.
Are you using structs in Array?
This way, you may be accessing the copies, they are not reference types in C#.
public struct PointStruct
{
public int X;
}
public class PointClass
{
public int X;
}
[TestMethod]
public void TestStruct()
{
var structArray = new PointStruct[1];
var classArray = new PointClass[1];
int x;
x = structArray[0].X;
try
{
x = classArray[0].X;
}
catch(NullReferenceException e)
{
Console.WriteLine(e.Message);
}
classArray[0] = new PointClass();
// It's now ok
x = classArray[0].X;
var point1 = structArray[0];
var point2 = classArray[0];
point1.X = 1;
point2.X = 1;
Assert.IsTrue(point2.X == 1);
Assert.IsFalse (structArray[0].X == 1);
structArray[0].X = 1;
Assert.IsTrue(structArray[0].X == 1);
}
I had googled my problem and was take here, I used the answers here to do mine.
When a user clicked a button I wanted the code to be carried out in another class called Logic. My main class was called MainWindow.
I had an array of colors linked to two rectangles in MainWindow. In order to be able to access the values stored in the array i simply had to do this.
public partial class MainWindow : Window
{
Rectangle[] choice;
SolidColorBrush black;
Became
public static Rectangle[] choice;
public static SolidColorBrush black;
}
in my Logic class to access it I had to do this.
MainWindow.choice[0].Fill = MainWindow.black;
Hope that helps anyone at all.
Related
Title might be a bit misleading
I have a string array. That I would like to pass by reference.
I know it can be accomplished simply by
public class test{
string[] content = {"abc", "abd"};
ViewContent vc = new ViewContent();
public static void Main()
{
vc.InitView(content);
}
}
public class ViewContent{
string[] contentToView;
public void InitView(ref string[] contentToShow)
{
contentToView = contentToShow;
View();
}
public void View()
{
//Do whatever with contentToView
//Example
Array.Resize<string> (ref contentToView, someInt);
}
}
If I were to resize the array with
Array.Resize()
The reference breaks and any further edits upon the resized array is not reflected on the main array from test class.
My question is:
How do I prevent the reference to the main array from breaking when the need arises for me to resize it?
Rephrase
How do I resize contentToView while also resizing content in test class?
Yes, I know it would be simpler to use Lists but I am experimenting with Arrays.
Yes, I know my problems would be solved if I pass in the test object instead of just an array. I am avoiding this method because I have other objects that have string arrays as well. You might ask that if I have other objects, that serve similar functions I could use inheritance and take in the base class to ensure that all my content can be shown. This is something I would like to avoid.
How do I prevent the reference to the main array from breaking when the need arises for me to resize it?
You don't. You just don't use an array. Array objects aren't resizable, and after you've copied the value of contentToShow into contentToView, any further changes to the contentToShow variable are ignored, and likewise in reverse.
What you're asking is for contentToView to change its value (which is a reference) every time content in your test class changes, or vice versa. There's no way of achieving that. You could introduce another level of indirection with a Wrapper<T> class you'd write which basically looks like this:
public class Wrapper<T>
{
public T Value { get; set; }
}
If you then made test.content and ViewContent.contentToView both Wrapper<string[]> fields, then if you change test.content.Value, you'd see that change in ViewContent.contentToView.Value... but I would advise against it.
There is no way to resize array itself. Array.Resize method creates new array. So in anyway your old reference will not work. Also there is no sense to use ref keyword in your code. It can be useful only if you will reassign contentToShow inside InitView method. You have to use some class (List or your own class) if you want to "resize" your array (reassign it to the new array).
I am new to C#. Come from the C/C++ environment. My application has a List<Model> which is required all over the place, by different classes. The problem is that a copy will not do because this statement:
dataGrid.ItemsSource = myModelList;
requires the original by address. I tried changing some arguments around and passing that particular variable as ref but as soon as it is assigned with an equal sign, I end up with a copy. Correct?
You could make it a singleton.
However a concrete List needed all over the place would make me have a serious think about my design.
At the very least you should consider writing a class to control access to the list (add, remove, clear etc), and making that "global", otherwise you are going to be in deep in the brown stuff, until it hits the fan.
Create a Public Class and have the content you wish to pass declared static within the class. Then just access it as NameOfClass.NameOfMethod()
public class NameOfClass
{
public static RETURNTYPE NameOfMethod()
{
// Your Code
}
}
You can create a public class for it with a public static List inside it. That one you then can access everywhere.
eg
public class FakeGlobal
{
public static List<Model> MyModelList = new List<Model>();
}
or even make it a property with getter/setter.
I am working on a project and I have an object, upon instantiation of which, will have a large number of values (20+) passed into it. I know I could make a constructor that would take in all of the values, but I am looking for a cleaner / more efficient way to do this.
Just to put this in perspective, the object is a character in a game, new instances of which are frequently created. The values assigned are attributes which are randomly generated.
Is a constructor with a large number of arguments the best way to go? Or is there a better way to do this that I don't know about? Any advice would be greatly appreciated.
EDIT: When a new game starts, a List<Character> is created and a for loop creates 10 instances of character and adds them to the list.
You can create a call that defines your game character. have users populate that class and pass it as the argument to your class.
something like this,
public class CharecterInfo
{
public string Name {get;set;}
public int Power {get;set;}
public int Health{get;set;}
}
public class Charecter
{
public Charecter(CharecterInfo charecterInfo)
{
//import values
}
}
I would avoid using public properties, since your class could be used while it's not properly initialized (in a bad state) which is the job of the constructor. you should use a constructor and validate the input before allowing the user to continue.
If the properties have public setters, you can use the object initialization syntax, e.g.:
Character c = new FooCharacter() {
Name = "Ugly Monster",
HP = 10000,
....,
};
Edit: as pointed out in the comments, this assumes that your constructor (empty or with minimal parameters) will initialize all required properties with valid data. The initialization syntax is just syntactic sugar that sets any specified properties after the constructor has initialized the object.
This completely depends on what those arguments are... But generally, it's not a great idea to have huge parameter lists. This is because of the confusion it creates over which parameter is what. An exception to this would be where you have a variable-length argument list that takes key/value pairs, allowing you to pass your data in an undefined order.
One alternative is to make another class that represents all your arguments. You could just create an instance of this, set the relevant fields and pass that in. To extend the idea, you might break that class up into a few classes and then provide a handful of constructors that take different combinations of those.
The useful thing with this approach is that you can have a default value for any of the arguments. Normally, if you want to specify a value for something further down the argument list but use defaults for the rest, you have to fill in all the default values in between. With this approach you can use all defaults except for the values you want to specify.
You have several options:
If all of the values are required:
Stick with the large list of parameters
Create a new class which has all of these items as properties
If not all of the values are required and you can use the Builder-pattern:
This link describes the pattern in detail: http://cdmckay.org/blog/2009/07/03/joshua-blochs-builder-pattern-in-csharp/
You can make a method that returns a class instance. Perhaps even in that class itself.
Something like:
public class Character
{
public string Name;
public int Level;
static Random random = new Random();
public static Character CreateNew()
{
Character newOne = new Character();
newOne.Level = random.Next(1, 5);
newOne.Name = (random.Next(1, 2) == 1) ? "Me" : "You";
return newOne;
}
}
One possibility lies in OOAD itself. Character attributes sound like a big enough concern to be the responsibility of a distinct class with which your character class collaborates.
A quick CRC analysis of your domain may help identify one or more newly distinguished responsibilities & corresponding types that are missing presently.
I'm building a C# class for matrices. I actually found something on SO to get started with so I don't have to start from scratch. The guy's class has a private property for the rows and columns of the matrix and a get() and set() property. Sometimes the guy refers to the properties themselves by name mRowCount and mColumnCount or by the this.RowCount and this.ColumnCount inside the class for calculation purposes as seen below (I only added relevant code):
public class Matrix
{
private decimal[,] mInnerMatrix;
private int mRowCount, mColumnCount = 0;
public int RowCount
{
get { return mRowCount; }
}
public int ColumnCount
{
get { return mColumnCount; }
}
}
Sometimes in the code the guy uses the properties by name mRowCount and mColumnCount and other times using this.RowCount and this.ColumnCount instead of the former way. What is the difference? Is one way better and if so with respects to what? Particularly in boolean methods where the methods checks to see if the object/matrix is a diagonal, symmetric or square matrix the developer uses the this.RowCount and this.ColumnCount in the loops that run through the mInnerMatrix[] array that holds the matrix's data. Other times he uses the properties themselves. Can anyone explain why someone might do this or is it a mistake? What should I use and should I use it throughout the entire program?
Technically, the get and set methods can be not that straightforward. For instance if you don't store rows and cols count but instead store rows and total elements, you would have to divide total by rows to get cols:
public Cols {get {return _mTotal/_mRows;}}
This is not the best sample, but you can get the idea. In your simple case there will be no difference whether to use a field or a property (if you actually have set methods but omitted them, otherwise the properties are readonly!). But note that one day you might want to implement some logic in get. Then the code that's using properties would work fine but the code that's using fields would fail.
Outside a class you always have to use properties, if any. In fact, you would declare fields private so that only within the class you can access them. Technically you can use both fields and properties outside class, but that would lead to a chaos.
On the other hand I would disagree that mixing properties and fields access within a class is always discouraged. Sometimes you would really need this access, the easiest sample is when your property is readonly (has only get).
If you defined properties - use them wherever possible, inside or outside class, as they may contain additional logic, not only direct member access.
One valid reason not to use properties (use direct access instead) - in constructor,
every other access should be made using properties.
It's rather bad practice to mix direct access and properties within a class
I have GUI that allows an user to create and modify a point object. I need to store a list of these points to insert at a specific drawing.
Here's how I came up with it:
In the form code, I opened a private property List<Points> and I manipulate it directly inside form code. Is this the correct way to handle?
Something like:
public partial class TesteInterface_AdicionarVertice : Form {
public List<VerticeDNPM> listaVertices;
public TesteInterface_AdicionarVertice()
{
InitializeComponent();
listaVertices = new List<VerticeDNPM>();
}
}
So, what do you think about this design? Is there a better way to do it?
Thanks for all thoughs.
I will make the list read-only. thanks for that idea.
The real thing here is this: I have a button which creates points, and another that creates polygons from points.
I need to have a way to get the List of points at the time the user chooses to create that certain polygon. That is basically what i am asking :P
I though to use a class property (in this case List) to store temp points, until the user creates the polygon. Is this a valid approach?
Sorry for that. The correct code is:
public partial class TesteInterface_AdicionarVertice : Form
{
public List<VerticeDNPM> listaVertices;
public TesteInterface_AdicionarVertice()
{
InitializeComponent();
listaVertices = new List<VerticeDNPM>();
}
}
Assuming that you include the appropriate namespace inclusions and class definitions, then what you have posted is valid and does not clearly violate any best practices (unless you count naming conventions, in which case VerticeDNPM should be VerticeDnpm according to Microsoft's naming guidelines). However, in order critique your approach from a design standpoint, you'd really need to provide more information.
Thanks for all thoughs.
I will make the list read-only. thanks for that idea.
The real thing here is this:
I have a button which creates points, and another that creates polygons from points.
I need to have a way to get the List of points at the time the user chooses to create that certain polygon. That is basically what i am asking :P
I though to use a class property (in this case List) to store temp points, until the user creates the polygon. Is this a valid approach?
I'm not really sure what you are asking. Aside from moving your non-UI code out of the UI, I would change the list creation to a readonly field like so:
public partial class TesteInterface_AdicionarVertice : Form {
private readonly List<VerticeDNPM> listaVertices = new List<VerticeDNPM>();
public List<VerticeDNPM> Vertices {get; set;};
public TesteInterface_AdicionarVertice()
{
InitializeComponent();
}
}
I agree that making your list public is a bad idea as then a consumer of the class can modify the actual list object itself, which is not what you want. Instead you want to expose it as a read-only property thereby allowing consumers to access the list contents.
public partial class TestInterface_ADicionaryVertice : Form
{
private List<VerticeDNPM> listVertices = new List<VerticeDNPM>();
public List<VerticeDNPM> { get { return listVertices; } }
public TestInterface_ADiciontaryVertice()
{
InitializeComponent();
...manipulate list of points here...
}
}
In this way you are modifying a private list of points in your code while still allowing a consumer (presumably something that receives the form as a parameter?) to access the list of points and read through it.
Two additional thoughts:
1) If the only consumer is deriving from this form instead of operating on it (receiving it as a parameter somewhere) then consider making the list protected instead.
2) If you do not want the list to be modified by any consumer (i.e. the list of points can't change once you're done manipulating them) then consider exposing an enumerator for the list instead of the list itself. This way someone can enumerate the points but can't change them.
Example:
public IEnumerator GetPoints { get { return listVertices.GetEnumerator(); } }
If you give a user access to a read-only property and return the original list, then the a consumer could still modify that list. The List is still a reference type, so the property is returning a pointer to the list. A true read-only property will create a copy of the list inside the 'get' and return that instead.
I wouldn't make your list public. Then you never know who is modifying it. Make your list private, then expose it as read only.
You can read more about it here. You can also run your code through FxCop. I'm sure it would pick this up.