How can I store an Object in an Array? [duplicate] - c#

This question already has answers here:
Print out object elements from list [duplicate]
(2 answers)
Print List of objects to Console
(3 answers)
print list<object> in console c# [duplicate]
(2 answers)
Closed 2 years ago.
I'm learning to code. I have started a little project where I design a text-based RPG.
I am struggling with storing and retrieving objects in and from an array.
Please have a look at my progress so far and tell me what I am doing wrong.
If I am using a wrong approach please also let me know how to do the whole thing smarter :)
First I define some properties of the player:
static class Globals
{
public static string playername;
...
public static object[] playerInventory = new object[4];
}
Then I create the weapon class:
public class Weapon
{
public string weaponName;
public int weaponBaseDamage;
public Weapon(string name, int baseDamage)
{
weaponName = name;
weaponBaseDamage = baseDamage;
}
Then I create the first basic weapon and try to store it in an array.
public class Program
{
public static void Main()
{
Weapon StartSword = new Weapon("My first Sword", 1);
Globals.playerInventory[0] = StartSword;
Console.WriteLine(StartSword.weaponName); // This works
Console.WriteLine(Globals.playerInventory[0]); // This prints "CSharp_Shell.Weapon", but I expected "StartSword"
Console.WriteLine(Globals.playerInventory[0].weaponName); // This results in an Error
The unexpected result of the second WriteLine command tells me that something must be quite wrong, but I don't know what it is and how to fix it. Any advice is welcome! (And please keep in mind that I am new to Coding).

It's required Typecasting. Please try like below:
Console.WriteLine(((Weapon)Globals.playerInventory[0]).weaponName)

Ok, lets look at what your code does:
Weapon StartSword = new Weapon("My first Sword", 1);
Globals.playerInventory[0] = StartSword;
Console.WriteLine(StartSword.weaponName); // This works
Above you create an object of the type Weapon with the name "My first Sword". And then print the name of that public property that is populated in the constructor.
Console.WriteLine(Globals.playerInventory[0]); // This prints "CSharp_Shell.Weapon", but I expected "StartSword"
Here you try to write an object. But an object is not a string so c# will automatically try to convert that to a string and will look at the type. So it is expected that it will not write the properties but a representation of the type.
Console.WriteLine(Globals.playerInventory[0].weaponName); // This results in an Error
Globals.playerInventory is defined as object[] playerInventory, so even if we know that you have entered an object of type weapon there, we need to specify that. Either by letting playerInventory be of the type Weapon[] playerInventory, or by type casting your object before using its properties, like this:
Console.WriteLine(((Weapon)Globals.playerInventory[0]).weaponName);

Related

How to access property of a class whose name is in a variable [duplicate]

This question already has answers here:
How to get a property value based on the name
(8 answers)
Closed 3 years ago.
I have a class with is a collection of XPaths. I want to pass the name of the field and want to get the XPath for that field. The problem here is I have to store the passed value in a variable and putting an if condition to check for the corresponding XPath variable as shown below.
As of now, I am using the if condition and I can use switch condition as well but this solution is not feasible as the collection of XPath will grow and it will become unmanageable.
class Program
{
static void Main(string[] args)
{
Console.WriteLine(new Program().IReturnXpath("LastName"));
}
public string IReturnXpath(String nameOfField)
{
if (nameOfField.Equals("Lastname"))
return new XpathCollection().Lastname;
else if (nameOfField.Equals("Firstname"))
return new XpathCollection().Firstname;
else
return "Xpath not found";
}
class XpathCollection
{
public string Lastname = "xpath for lastname";
public string Firstname = "xpath for firstname";
}
}
Let me explain how Microsoft solved exact same problem.
System.Drawing.Color has many properties each reflecting a single color. Color also has a FromName method which allows you to find a color by string parameter. Almost exactly your problem.
As you can see in their, implementation, they create a Hashtable and by using reflection they fill it. Next time someone asks for a color they just lookup and return it. Put generation code in a static constructor and you are done.
https://referencesource.microsoft.com/#System.Drawing/commonui/System/Drawing/ColorConverter.cs,d06a69beb42834b2

Pass list of objects to web-service [duplicate]

This question already has answers here:
Sending array of objects to WCF
(3 answers)
Closed 5 years ago.
I have an array of objects
let arr = [{"1":"bar"},{"2":"bar"}]
which gets sent to a service through ajax inside data
the service will then get the array & do stuff.
[WebInvoke]
public void getStuff(params Model[] data)
{
// do stuff
}
what would my model need to look like to receive the data arr?
Update:
changed keys in object
You can do something like this to get the params:
var key = Request.Params[0];
then you can use the var "key" to fill a model
The elemenst in this .js array:
let arr = [{"foo":"bar"},{"foo":"bar"}]
Could be represented as this .cs class
class Model
{
public string foo;
}
Because for each object (the bit inside the {}), the default is to map the lhs to a property of the class with the same name (foo).
But, after your edit, if you want this:
let arr = [{"1":"bar"},{"2":"bar"}]
Then that cannot map to a class so easily, not leat because you can't have a field named '1' but also because it implies that there are many many different options for the lhs of the json.
In that case, consider using a Dictionary

An interview riddle: accessing a private data member [duplicate]

This question already has answers here:
Access private fields
(4 answers)
Closed 6 years ago.
I recently had an interview with C# questions. One of them I cannot find an answer to.
I was given a class, looks like this:
public class Stick
{
private int m_iLength;
public int Length
{
get
{
return m_iLength;
}
set
{
if (value > 0)
{
m_iLength = value;
}
}
}
}
Also, a main class was given
static void Main(string[] args)
{
Stick stick = new Stick();
}
The task was to add code to the main that will cause m_iLength in the Stick class to be negative (and it was stressed out that it can be done).
I seem to miss something. The data member is private, and as far as I know the get and set function are by value for type int, so I do not see how this can be done.
Reflection is always the most direct:
var type = typeof(Stick);
var field = type.GetField("m_iLength", BindingFlags.NonPublic |BindingFlags.GetField | BindingFlags.Instance);
field.SetValue(stick, -1);
Console.WriteLine(stick.Length);
Explanation:
The first line gets the Type object for Stick, so we can get the private fields later on.
The second line gets the field that we want to set by its name. Note that the binding flags are required or field will be null.
And the third line gives the field a negative value.

C# how to copy templet object data to a new object , but no the address [duplicate]

This question already has answers here:
Deep cloning objects
(58 answers)
How do you do a deep copy of an object in .NET? [duplicate]
(10 answers)
Closed 8 years ago.
i basically want to define a templet data object ,
and use this templet data object to assign new data objects.
then put different values to new data objects.
code like:
public class sData
{
public string name;
public int Number;
public sData(string name,int Number)
{
this.poster_path = path;
this.Number = Number;
}
}
sData templet= new sData("aaaa","0");
sData realData1 = new sData();
realData1=templet;
realData1.Number=100;
but after realData1.Number=100;
i found the templet.Number is changed to 100
how can i just give the 100 to realData1 , but no the templet ?
Am I correct in saying that you'd like to setup some a factory object which will create data objects with pre-defined set of values (i.e. a template)?
The code you have above won't do that. You have only created one object but you have two different references to it.
Perhaps something like this will do what you need:
public class sData
{
public string name;
public int Number;
public sData(string name,int Number)
{
this.poster_path = path; //copied from question, this might need updating.
this.Number = Number;
}
sData CreateCopy()
{
return new sData(name, number);
}
}
sData template = new sData("aaaa","0");
sData realData1 = template.CreateCopy();
realData1.Number=100;
This still doesn't feel very elegant, perhaps separate classes for the factory and the data object would be more appropriate, but it's hard to say without more context.
You are assigning the object variable of templet to realData1 and this way you are still referencing the same object in memory:
realData1=templet;
You can assign the values instead of the object itself:
realData1.name = templet.name;
realData1.Number = templet.Number;
Class is of reference type and the reference variables of class sData realData1 and templet point to the same memory location in heap, so the value of templet is getting overwritten by the value realData1.

how to create multiple objects and enumerate them in c#

my problem is as follows:
Im building a console application which asks the user for the numbers of objects it should create and 4 variables that have to be assigned for every object.
The new objects name should contain a counting number starting from 1.
How would you solve this?
Im thinking about a class but im unsure about how to create the objects in runtime from userinput. Is a loop the best way to go?
What kind of class, struct, list, array .... would you recommend. The variables in the object are always the same type but i need to name them properly so I can effectivly write methods to perform operations on them in a later phase of the program.
Im just learning the language and I would be very thankful for a advice on how to approach my problem.
If I understand your problem correctly:
class MyClass
{
public int ObjectNumber { get; set; }
public string SomeVariable { get; set; }
public string AnotherVariable { get; set; }
}
// You should use keyboard input value for this
int objectsToCreate = 10;
// Create an array to hold all your objects
MyClass[] myObjects = new MyClass[objectsToCreate];
for (int i = 0; i < objectsToCreate; i++)
{
// Instantiate a new object, set it's number and
// some other properties
myObjects[i] = new MyClass()
{
ObjectNumber = i + 1,
SomeVariable = "SomeValue",
AnotherVariable = "AnotherValue"
};
}
This doesn't quite do what you described. Add in keyboard input and stuff :) Most of this code needs to be in some kind of Main method to actually run, etc.
In this case, I've chosen a class to hold your 4 variables. I have only implemented 3 though, and I've implemented them as properties, rather than fields. I'm not sure this is necessary for your assignment, but it is generally a good habit to not have publically accessible fields, and I don't want to be the one to teach you bad habits. See auto-implemented properties.
You mentioned a struct, which would be an option as well, depending on what you want to store in it. Generally though, a class would be a safer bet.
A loop would indeed be the way to go to initialize your objects. In this case, a for loop is most practical. It starts counting at 0, because we're putting the objects in an array, and array indexes in C# always start at 0. This means you have to use i + 1 to assign to the object number, or the objects would be numbered 0 - 9, just like their indexes in the array.
I'm initializing the objects using object initializer syntax, which is new in C# 3.0.
The old fashioned way would be to assign them one by one:
myObjects[i] = new MyClass();
myObjects[i].ObjectNumber = i + 1;
myObjects[i].SomeVariable = "SomeValue";
Alternatively, you could define a constructor for MyClass that takes 3 parameters.
One last thing: some people here posted answers which use a generic List (List<MyClass>) instead of an array. This will work fine, but in my example I chose to use the most basic form you could use. A List does not have a fixed size, unlike an array (notice how I initialized the array). Lists are great if you want to add more items later, or if you have no idea beforehand how many items you will need to store. However, in this case, we have the keyboard input, so we know exactly how many items we'll have. Thus: array. It will implicitly tell whoever is reading your code, that you do not intend to add more items later.
I hope this answered some questions, and raised some new ones. See just how deep the rabbit hole goes :P
Use a list or an array. List example:
int numberOfObjects = 3;
List<YourType> listOfObjects = new List<YourType>();
for(int i = 0 ; i < numberOfObjects ; i++ )
{
// Get input and create object ....
// Then add to your list
listOfObjects.Add(element);
}
Here, listOfObjects is a Generic list that can contain a variable number of objects of the type YourType. The list will automatically resize so it can hold the number of objects you add to it. Hope this helps.
If I understood what you are asking you could probably do something like this:
class Foo
{
private static int count;
public string name;
public Foo(...){
name = ++count + "";
}
}
I'm guessing what you're trying to do here, but this is a stab in the dark. The problem I'm having is dealing with the whole "the new objects name should contain a counting number starting from 1" thing. Anyway, here's my attempt:
public class UserInstantiatedClass
{
public int UserSetField1;
public int UserSetField2;
public int UserSetField3;
public int UserSetField4;
public string UserSpecifiedClassName;
}
public static class MyProgram
{
public static void Main(string [] args)
{
// gather user input, place into variables named
// numInstances, className, field1, field2, field3, field4
List<UserInstantiatedClass> instances = new List< UserInstantiatedClass>();
UserInstantiatedClass current = null;
for(int i=1; i<=numInstances; i++)
{
current = new UserInstantiatedClass();
current.UserSpecifiedClassName = className + i.ToString(); // adds the number 1, 2, 3, etc. to the class name specified
current.UserSetField1 = field1;
current.UserSetField2 = field2;
current.UserSetField3 = field3;
current.UserSetField4 = field4;
instances.Add(current);
}
// after this loop, the instances list contains the number of instances of the class UserInstantiatedClass specified by the numInstances variable.
}
}

Categories

Resources