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).
Related
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 the following class:
public class Humptydump
{
public Humptydump()
{ }
public Rectangle Rectangle { public get; private set; }
}
in this class the Rectangle class comes from system.drawing,
how do i make it so people cannot access the methods of the rectangle, but can get the rectangle itself?
In your case, it will "just work".
Since Rectangle is a struct, your property will return a copy of the Rectangle. As such, it will be impossible for anybody to modify your Rectangle directly unless you expose methods to allow this.
That being said, it's impossible, in general, to provide access to a type without also providing access to methods defined on the type. The methods go along with the type. The only alternative in those cases would be to create a new type that exposed the data you choose without the data or methods you wish to be exposed, and provide access to that.
If rectangle was not a struct, one possible thing would be deriving it and hiding those methods:
public class DerivedClass : BaseClass
{
new private SomeReturnType SomeMethodFromBaseClasse(SameParametersAsInBaseClassAndSameSignature
{
//this simply hides the method from the user
//but user will still have the chance to cast to the BaseClass and
//access the methods from there
}
}
Are you talking about the Rectangle object specifically, or on a more general term and just using that as an example?
If you're talking on a more general term, this is something that comes up very often in refactoring patterns. This most commonly happens with collections on objects. If you expose, for example, a List<T> then even if the setter is private then people can still modify the collection through the getter, since they're not actually setting the collection when they do so.
To address this, consider the Law of Demeter. That is, when someone is interacting with a collection exposed by an object, should they really be interacting with the object itself? If so, then the collection shouldn't be exposed and instead the object should expose the functionality it needs to.
So, again in the case of a collection, you might end up with something like this:
class SomeObject
{
private List<AnotherObject> Things;
public void AddAnotherObject(AnotherObject obj)
{
// Add it to the list
}
public void RemoveAnotherObject(AnotherObject obj)
{
// Remove it from the list
}
}
Of course, you may also want to expose some copy of the object itself for people to read, but not modify. For a collection I might do something like this:
public IEnumerable<AnotherObject> TheObjects
{
get { return Things; }
}
That way anybody can see the current state of the objects and enumerate over them, but they can't actually modify it. Not because it doesn't have a setter, but because the IEnumerable<T> interface doesn't have options to modify the enumeration. Only to enumerate over it.
For your case with Rectangle (or something similar which isn't already a struct that's passed by value anyway), you would do something very similar. Store a private object and provide public functionality to modify it through the class itself (since what we're talking about is that the class needs to know when its members are modified) as well as functionality to inspect it without being able to modify what's being inspected. Something like this, perhaps:
class SomeObject
{
private AnotherObject Thing;
public AnotherObject TheThing
{
get { return Thing.Copy(); }
}
public void RenameThing(string name)
{
Thing.Name = name;
}
// etc.
}
In this case, without going into too much detail about what AnotherObject is (so consider this in some ways pseudo-code), the property to inspect the inner object returns a copy of it, not the actual reference to the actual object. For value types, this is the default behavior of the language. For reference types, you may need to strike a balance between this and performance (if creating a copy is a heavy operation).
In this case you'll also want to be careful of making the interface of your object unintuitive. Consuming code might expect to be able to modify the inner object being inspected, since it exposes functionality to modify itself. And, indeed, they can modify the copy that they have. How you address this depends heavily on the conceptual nature of the objects and how they relate to one another, which a contrived example doesn't really convey. You might create a custom DTO (even a struct) which returns only the observable properties of the inner object, making it more obvious that it's a copy and not the original. You might just say that it's a copy in the intellisense comments. You might make separate properties to return individual data elements of the inner object instead of a single property to return the object itself. There are plenty of options, it's up to you to determine what makes the most sense for your objects.
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 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.
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.