C#: Why does my list not print the items? [duplicate] - c#

This question already has answers here:
question about print List<T> to screen
(5 answers)
Print List of objects to Console
(3 answers)
Print list Object c#
(1 answer)
Why does every line in the .txt-file output end with 'System.int32'? C#
(3 answers)
Closed 2 years ago.
I'm trying to print out the int items inside the list but I get the following output, which is obviously not what I want to print:
YSolution.Dice
YSolution.Dice
YSolution.Dice
YSolution.Dice
YSolution.Dice
Source code:
class Dice
{
//defining variable and properties
private bool _hold = false;
private Random rnd;
public int Current { get; private set; }
public bool IsHolding
{
get { return _hold; }
set { _hold = value; }
}
public Dice()
{
Current = 0;
rnd = new Random(Guid.NewGuid().GetHashCode());
FRoll();
}
public int FRoll()
{
Current = rnd.Next(1, 7);
return Current;
}
class DiceCup
{
public List<Dice> Dices { get; } = new List<Dice>();
public DiceCup(int count)
{
for (int i = 0; i < count; i++)
{
Dices.Add(new Dice());
}
foreach (Dice aDice in Dices)
{
Console.WriteLine(aDice);
}
}
class Program
{
static void Main(string[] args)
{
DiceCup nbd = new DiceCup(count);
}
}
The method FRoll(); seem to not get called in the dice class for some reason, when a new item is added to the list.I really just want to print out the items in the List Dices but I do not get the output/result I want. Anyone who can spot the error?

Currently you're just calling ToString() on your Dice object. Since you haven't overriden ToString() this is just using the default object.ToString() implementation which returns the type name of the object (YSolution.Dice in your case).
You have a Current property on your dice that returns the value of the dice, if you call this method then that will return the value of the dice, which you can then print: change Console.WriteLine(aDice); to Console.WriteLine(aDice.Current);.
Alternatively, as others have pointed out, you can override ToString() on your Dice class to return the current value of the dice:
class Dice
{
//defining variable and properties
private bool _hold = false;
private Random rnd;
public int Current { get; private set; }
public bool IsHolding
{
get { return _hold; }
set { _hold = value; }
}
public Dice()
{
Current = 0;
rnd = new Random(Guid.NewGuid().GetHashCode());
FRoll();
}
public int FRoll()
{
Current = rnd.Next(1, 7);
return Current;
}
public override string ToString()
{
return Current.ToString();
}
}

you want to implement the ToString-method:
public string ToString()
{
return Current.ToString();
}

Besides overriding the ToString method, as mentioned in other answers, you could also collect the results from the dice and print those:
foreach (int result in Dices.Select(d => d.Current))
{
Console.WriteLine(result);
}
The Select method is defined in the System.Linq namespace.

Related

How to use a Stack's Pop method in another method

I am attempting to write a program for an assignment that Pops and adds the first 2 items in a Stack. The program has a Pop method, but I would like to know how to call the method within the Add method. This Add is supposed to Pop the top two items in a stack, get their sum, and Push that sum to the stack. In my code below I call the Pop method twice inside the Add method, but when I display the stack, the stack still has all of the original values. Is there something more/else I need to go to get the Pop method to work?
class StackEmptyException : ApplicationException
{
public StackEmptyException(String message) : base(message)
{
}
}
class MathStack
{
private int[] dataStack;
private int size;
private int top = -1;
public bool IsEmpty()
{
return top == -1;
}
public bool IsFull()
{
return top == size - 1;
}
public void Push(int i)
{
dataStack[++top] = i;
}
public int Pop()
{
if (IsEmpty())
throw new StackEmptyException
("Stack empty -- cannot pop");
else
return dataStack[top--];
}
public int Top()
{
if (IsEmpty())
throw new StackEmptyException
("Stack empty -- top undefined");
else
return dataStack[top];
}
public MathStack()
{
dataStack = new int[10];
}
public MathStack(int s)
{
size = 10;
dataStack = new int[size];
}
public void LoadStack(int v)
{
dataStack[++top] = v;
}
public void Display()
{
int[] display = new int[dataStack.Length];
for (int i = 0; i < dataStack.Length; i++)
{
display[i] = dataStack[i];
Console.WriteLine("{0}", display[i]);
}
}
public void Add()
{
int add1 = dataStack[0];
int add2 = dataStack[1];
Pop();
Pop();
int sum = add1 + add2;
Console.WriteLine("Sum: {0}", sum);
}
}
class Program
{
static void Main(string[] args)
{
MathStack stack1 = new MathStack();
stack1.Push(9);
stack1.Push(8);
stack1.Push(7);
stack1.Push(6);
stack1.Push(5);
stack1.Push(4);
stack1.Push(3);
stack1.Push(2);
stack1.Push(1);
stack1.Push(0);
stack1.Display();
stack1.Add();
stack1.Display();
Console.ReadLine();
}
}
There are two things wrong with your code.
First, the Display method displays the whole array. Except that since you're not physically removing the items from the array, you need to stop at the index top:
public void Display()
{
if (IsEmpty())
{
Console.WriteLine("Empty");
return;
}
for (int i = 0; i <= top; i++)
{
Console.WriteLine(dataStack[i]);
}
}
The second issue is your Add. From what I understand, you want to pop the last two items, sum them, and push the result. In your implementation, you are actually summing the first two items (not the last two). A better version would be:
public void Add()
{
int add1 = Pop();
int add2 = Pop();
int sum = add1 + add2;
Console.WriteLine("Sum: {0}", sum);
Push(sum);
}
Notice how I do not directly access dataStack. If your API is correctly implemented, it should not be needed.

How can I populate a string array with a parameter method C#

I am trying to populate a string array called "items" with a pre written method called "insert".
The project has pre written code "b.insert("apple");" etc etc and the method given is "public void insert(T item)". I have to write the code in this method to make the "insert" function work. I have to pass "item" into "items" array but my for loop simply gives me the output "milk" 10 times. Because of this, I know that "item" value is simply changing to the last string passed in the insert method. Would I have to write a nested for loop where "item" is a counter? In this case "item" cannot be a counter because it is a string type. Should I convert "item" into an array?
I'm not sure why such a seemingly simple task has me stumped by I've been at it for hours and at this point I just want to sort it out for the sake of sanity.
thanks in advance
class Program
{
static void Main(string[] args)
{
BoundedBag<string> b = new BoundedBag<string>("ShoppingList", 10);
b.insert("apple");
b.insert("eggs");
b.insert("milk");
Console.WriteLine(b);
Console.ReadKey();
}
}
public interface Bag<T> where T : class
{
void insert(T item);
string getName();
bool isEmpty();
}
public class BoundedBag<T> : Bag<T> where T : class
{
private string bagName; // the name of the bag
protected int size; // max size of the bag
private int lastIndex;
protected T[] items;
public BoundedBag(string name, int size)
{
bagName = name;
this.size = size;
rnd = new Random();
items = new T[size];
}
public string getName()
{
return bagName;
}
public bool isEmpty()
{
return lastIndex == -1;
}
public bool isFull()
{
if(items.Length >= size)
{
return true;
}
else { return false;}
}
public void insert(T item)
{
// fill in the code as directed below:
// insert item into items container
// throws FullBagException if necessary
for (int i = 0; i < size; i++)
{
items[i] = item;
}
}
}
You only want to insert one item into your array on insert so you shouldn't have a loop at all. Use the lastIndex field to insert one item into the appropriate place in the array:
public void insert(T item)
{
// fill in the code as directed below:
// insert item into items container
// throws FullBagException if necessary
if(isFull())
{
throw new FullBagException();
}
items[++lastIndex] = item;
}
Unfortunately your isFull method is also broken and your isEmpty method won't work properly unless you change the constructor.
public BoundedBag(string name, int size)
{
bagName = name;
this.size = size;
items = new T[size];
lastIndex = -1;
}
public bool isFull()
{
return lastIndex == size - 1;
}

How to make an array of objects visible to other functions

In my current program I am building an array of objects and then populating it, however I need to then access this populated array from another function within the same class. In C I would do this by making the array global, but global variables dont exist in C# and when I try to use the "Static" parameter it says arrays cant be static.
namespace FormsTest1
{
public partial class Form1 : Form
{
public int AppCount;
public static applications[] appList;
public Form1() //Main Entry point of program
{
IEnumerable<int> apps = VolumeMixer.EnumerateApplications();
AppCount = apps.Count();
int i = 0;
applications[] appList = new applications[AppCount];
foreach (int app in apps)
{
appList[i] = new applications();
appList[i].setProcessID(app);
appList[i].populate();
i++;
}
for (int j = 0; j < AppCount; j++) { ChannelSelect1.Items.Add(appList[j].Name); }
}
private void ChannelSelect1_SelectedIndexChanged(object sender, EventArgs e)
{
for (int k = 0; k < AppCount; k++)
{
if (ChannelSelect1.Text == appList[k].Name) //<-- This array is not the one I populate in Form1()
{ Channels[0] = appList[k].PID; }
}
}
public class applications
{
public int PID;
public string ProcessName;
public string WindowName;
public string Name;
public string Path;
public void setProcessID(int ID) { PID = ID; }
public string getProcessName() { return ProcessName; }
public string getWindowName() { return WindowName; }
public string getName() { return Name; }
public string getPath() { return Path; }
public void populate()
{
//stuff
}
}
}
I cant pass the array into the other functions cause they are event driven, and I need the index-ability of arrays.
How do I declare and populate an array of objects in one function, and then use that array in another function in the same class?
Change your constructor from
applications[] appList = new applications[AppCount];
to
appList = new applications[AppCount];
You should initialize your instance field instead of creating a new local one.
Btw: It is not necessary to make the array static.

C# Mock a Class With an Internal Property Setter

I am trying to build a unit test.
The class Position is implemented in a third party library. But for my unit test I need the Size property to be set to a specific value.
public class Position
{
private double _size;
private double Size
{
get
{
return _size;
}
internal set
{
_size = value;
}
}
}
I read this post: How do you create a unit-testing stub for an interface containing a read-only member?
but could not figure out how to make it work for me.
This is the class under test (just a simplified example). The posargument in the CalcPositionMetric() method must be of type Position:
public class PositionMetrics
{
public PositionMetrics()
{}
public double CalcPositionMetric(Position pos)
{
return 2 * pos.Size;
}
}
Here is a piece of my unit test:
using NUnit.Framework;
using NMock;
[TestFixture]
public class PositionUnitTests
{
[Test]
public void TestPosition()
{
Mock<Position> tmpPosMock = mFactory.CreateMock<Position>();
tmpPosMock.Expects.One.GetProperty(v => v.Size).WillReturn(7); /* !!! Exception !!! System.ArgumentException : mock object position has a getter for property Size, but it is not virtual or abstract */
/* Execute Test with tmpPositions*/
PositionMetrics pm = new PositionMetrics();
double result = pm.CalcPositionMetric(tmpPosMock.MockObject)
Assert.AreEqual(14, result);
}
}
But as you can see I get an exception. Could somebody help me to resolve this problem? Any other solutions are also welcome!
Cheers
Konstantin
New answer for the updated question I suggest you to introduce some kind of a proxy interface for that. See the code below:
interface IPosition {
int Size { get; }
}
class Position { //in 3rd party lib
public int Size {
get { return 5; }
}
}
class RealPosition : IPosition { //use this as your real object instead of using Position directly
private Position position;
public RealPosition(Position position) {
this.position = position;
}
public int Size {
get { return position.Size; }
}
}
class MockPosition : IPosition { //use this for testing
public int Size{ get; set; }
}
public class Program {
static void Main(string[] args) {
var pos = new MockPosition { Size = 7 };
Console.WriteLine(Calc(pos)); //prints 14
Console.ReadLine();
}
static int Calc(IPosition pos) { //change your method signature to work with interface
return pos.Size * 2;
}
}
Old answer If the class is not sealed you don't need any mocking libraries. Just use the new modifier for the required properties like this:
class Position {
public int Size { get { return 5; } }
}
class MockPosition : Position {
public new int Size { get; set; }
}
....
var mock= new MockPosition();
mock.Size = 7;
To use these items in some sort of list you'll have to cast them like this:
var items = new List<Position>();
for (int i = 0; i < 5; i++) {
items.Add(new MockPosition { Size = i });
}
foreach (var item in items.Cast<MockPosition>()) {
Console.Write("{0}\t", item.Size); //prints 0 1 2 3 4
}
If it is sealed and the property is not virtual than you'll have to use some other techniques, Moq (which I guess you are using) does not allow that

With Statement in C# like that of AS3/GML

I'm making a game using Monogame, and I've been trying to figure out how to implement a function that acts similarly to AS3's and GML's with statement.
So far I have a system that works, but not entirely the way I want it to. I store my GameObjects in a Dictionary of Lists. This is so I can get to the specific type of object I want to access without having to loop through a list of ALL objects. The key used is the name of the type.
public static Dictionary<string, List<GameObject>> All =
new Dictionary<string, List<GameObject>>();
I access all of a specific type of object using AllOf. If a List containing that type exists in the Dictionary, it returns that List, else it returns an empty list.
public static List<GameObject> AllOf(Type type)
{
string key = type.Name;
if(All.ContainsKey(key))
{
return All[key];
}
return new List<GameObject>();
}
An example of how these are implemented
public override void Update(GameTime gameTime)
{
List<GameObject> list = Instance.AllOf(typeof(Dummy));
for(int i = 0; i < list.Count; i++)
{
list[i].Update(gameTime);
list[i].foo += bar;
}
}
But I'd rather use something similar to the AS3/GML with statement, which would also allow for other, non-member codes to be executed.
with(typeof(Dummy))
{
Update(gameTime);
foo += bar;
int fooBar = 2;
someObject.someMemberFunction(fooBar);
}
Is there a way to accomplish this? My end goal is just to make my code look a little cleaner, and make it easier to make a lot of changes without having to type out a for loop each time.
No such syntax exists in C#, but you can access methods within the for that have nothing to do with the collection:
public override void Update(GameTime gameTime)
{
List<GameObject> list = Instance.AllOf(typeof(Dummy));
for(int i = 0; i < list.Count; i++)
{
list[i].Update(gameTime);
list[i].foo += bar;
int fooBar = 2;
someObject.someMemberFunction(fooBar);
}
}
Note that you can also use foreach, which is a little cleaner if you don't need the indexer:
foreach(var item in list)
{
item.Update(gameTime);
item.foo += bar;
int fooBar = 2;
someObject.someMemberFunction(fooBar);
}
try
using(Object myObject = new Object()){
}
i think this might be what your looking to use?
I have a small solution for this use case. This may be a bit of a necropost, but it is a pretty neat solution. Additionally, I think all of the C# features that are required existed back when this question was asked.
You can do something very similar to the GML with(x){} by using some form of delegate as a parameter to a static method, and passing a lambda as that parameter. The function can even be genericised, and you can call it without the class name by the using static statement. You will need to explicitly provide the typed/named parameter, but it is possible. You would need to hook it up to your own types, but the general idea is:
namespace NiftyStuff {
public static class With {
public static void with<T>(Action<T> proc) where T : GameObj {
var typeName = typeof(T).Name;
foreach (var item in GameObj.AllOf(typeName)) { proc((T)item); }
}
}
public class GameObj {
private static Dictionary<string, List<GameObj>> All = new Dictionary<string, List<GameObj>>();
public static List<GameObj> AllOf(string name) {
return All.ContainsKey(name) ? All[name] : null;
}
public static void Add(GameObj foo) {
string typeName = foo.GetType().Name;
List<GameObj> foos = All.ContainsKey(typeName) ? All[typeName] : (All[typeName] = new List<GameObj>());
foos.Add(foo);
}
public float x, y, angle;
public GameObj() { x = y = angle = 0; }
public void Destroy() { AllOf(GetType().Name)?.Remove(this); }
}
public class Enemy : GameObj {
public float maxHealth, curHealth;
public Enemy() : base() { maxHealth = curHealth = 300; }
public Enemy(float health) : base() { maxHealth = curHealth = health; }
public bool Damage(float amt) {
if (curHealth > 0) {
curHealth -= amt;
return curHealth <= 0;
}
return false;
}
}
public class Pumpkin : GameObj {
public bool exists = false;
public Pumpkin() : base() { exists = true; }
public bool LookAt() { return (exists = !exists); }
}
}
Actually using the above code would work as follows:
using NiftyStuff;
using static NiftyStuff.With;
//...
with ((Enemy e) => {
if (e.Damage(50)) {
Log("Made a kill!"); // Whatever log function you have...
}
});
with ((Pumpkin p) => {
if (p.LookAt()) {
Log("You see the pumpkin");
} else {
Log("You no longer see the pumpkin");
}
});
While not exactly like GML's with statement, it would at least let you run code against all of the registered objects of some type.
One important note is that you can't destroy objects inside of a with this way (due to concurrent modification of a collection while iterating it). You would need to collect all objects to be destroyed, and then remove them from the list in All, typically in a game loop this is done at the end of a frame.
Hope this helps, despite being 2 years out of date.

Categories

Resources