I have issue (I think) with derived class. When I add some points to my list in Form 1, I can see count and iterate through listA, and it seems its okay. I have below code:
/* Add points to lists */
class A {
private Point _singlePoint;
protected List<Point> _listA = new List<Point>();
protected List<Point> _listB = new List<Point>();
//properties
public List<Point> listA {
get { return _listA; }
set { _listA = value; }
}
public Point singlePoint {
get { return _singlePoint; }
set { _singlePoint = value; }
}
public virtual void addToListA(Point a) { }
}
class B : A {
public override void addToListA(Point a) {
_listA.Add(a);
}
}
public partial class Form1 : Form {
A _myPoints = new B();
private void drawPoint()
{
for (int i = 0; i < int.Parse(txtBoxPointsCount.Text); i++)
{
_myPoints.singlePoint = new Point(rnd.Next(100, 300), rnd.Next(100, 300));
_myPoints.addToListA(_myPoints.singlePoint);
}
foreach(Point p in _myPoints.listA)
{
graph.FillEllipse(new SolidBrush(cPoint), p.X, p.Y, 6, 6);
}
}
}
In other class I want to do some math on points, but I got ArgumentOutOfRangeException
class D {
A _myPoints = new B();
public void calulations(int iterations) {
randomPoint = rnd.Next(0, _myPoints.listA.Count);
System.Windows.Forms.MessageBox.Show(_myPoints.listA.Count.ToString());
try {
for (int i = 0; i < _iterations; i++) {
//here some math
}
}
catch(ArgumentOutOfRangeException e) {
// here I got errors about no items in my list
}
} }
In class D, in MsgBox I got count = 0. Maybe I wrote classes in wrong way? Method drawPoint() is called before calculations().
Could you help? Thanks in advance :)
That is because you are operating two completely different objects,
You have created an object here
public partial class Form1 : Form
{
A _myPoints = new B();
and then in class D created another
class D
{
A _myPoints = new B();
So you are adding point to your first object and trying to access in other object.
Related
This question already has answers here:
Why not inherit from List<T>?
(27 answers)
Closed 2 years ago.
Problem
I have Point2D class as a base class, to store List of Points I normally use List<Point2D> but now I want to Add Additional Methods and Few Properties to List<Point2D> like ToString Method for Printing, sorting based on the specific coordinate, specific method to filter Points, I don't want to use Extention Methods.
Things I Tried
I made a new Point2DList Class who inherits List<Point2D> class which is working fine for normal use but when using FindAll Function it now returns List<Point2D> but I want it to return Point2DList.I know I can write my own method which accepts predicate delegate but that's too much work.
Code
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleAppTest
{
internal static class Program
{
private static void Main()
{
try
{
var points = new Point2DList();
points.Add(new Point2D(0, 0));
points.Add(new Point2D(10, 0));
points.Add(new Point2D(10, 10));
points.Add(new Point2D(0, 10));
Console.WriteLine(points.ToString());
Point2DList newPoints = points.FindAll((x) => x.X == 10);
}
catch (Exception)
{
throw;
}
finally
{
Console.ReadLine();
}
}
}
public class Point2DList : List<Point2D>
{
public override string ToString()
{
var sb = new StringBuilder();
sb.AppendLine("List of Points");
foreach (var pt in this)
{
sb.AppendLine(pt.ToString());
}
return sb.Remove(sb.Length - 1, 1).ToString();
}
}
public class Point2D
{
public int X { get; set; }
public int Y { get; set; }
public Point2D(int x, int y)
{
X = x;
Y = y;
}
public override string ToString()
{
return $"{X},{Y}";
}
}
}
It´s rarely neccessary to inherit from any collection-type - in particular as you just want to extent it, not change its implementation. Thus I´d go for composition over inheritance and use a field instead:
class Points2DList
{
private List<Point2D> _points;
public Points2DList(List<Point2D> points) { _points = points; }
public override string ToString() { ...}
public void Add(Point2D p { _points.Add(p); } // delegate to implementation of your underlying list
public Point2D this[int i] // delegate to implementation of your underlying list
{
get => _points[i];
set => _points[i] = value;
}
public Points2DList FindAll(Predicate<Point2D> P)
{
return new Points2DList(_list.FindAll(p));// delegate to implementation of your underlying list
}
}
This way you can control which functionality you really want to expose to clients. Using inheritance would expose every public member to the outside, which you probably don´t want. E.g. while you want to allow removing an element from your list, you may not want to enable clients to call Clear on it.
Another option is to just pass it to a new list. In Linq, the same thing happens when you for example call AsReadOnly or ToList etc.
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleAppTest
{
public static class Program
{
public static void Main()
{
try
{
var points = new Point2DList();
points.Add(new Point2D(0, 0));
points.Add(new Point2D(10, 0));
points.Add(new Point2D(10, 10));
points.Add(new Point2D(0, 10));
Console.WriteLine(points.ToString());
var newPoints = new Point2DList(points.FindAll((x) => x.X == 10));
Console.WriteLine(newPoints.ToString());
}
catch (Exception)
{
throw;
}
finally
{
Console.ReadLine();
}
}
}
public class Point2DList : List<Point2D>
{
public override string ToString()
{
var sb = new StringBuilder();
sb.AppendLine("List of Points");
foreach (var pt in this)
{
sb.AppendLine(pt.ToString());
}
return sb.Remove(sb.Length - 1, 1).ToString();
}
public Point2DList()
{
}
public Point2DList(IEnumerable<Point2D> ls)
: base(ls)
{
}
}
public class Point2D
{
public int X { get; set; }
public int Y { get; set; }
public Point2D(int x, int y)
{
X = x;
Y = y;
}
public override string ToString()
{
return X + "," + Y;
}
}
}
https://dotnetfiddle.net/WJM1O1
In windows Form App I get call
private Class1 c1;
private void Print()
{
c1 = new Class1();
}
but in next one i don't want to declare new Class because it make a wrong value for my program and get error.
it's like
private void Print2()
{
c1 ; //**( I don't want to declare new one )**
}
edit 2
i'd like to do like you said but argument in my code is like
public CandleCollection GetCandleCollection()
{
CandleCollection collection = null;
try
{
collection = SymbolList[cbxSymbol.Text];
}
catch (Exception) { }
return collection;
}
private Class1 c1 = new Class1(<collection>); **it's need to call collection**
private void Print()
{
c1 = new Class1();
}
private void Print2()
{
c1 ; //**( I don't want to declare new one )**
}
edit 3
This is my original code to call c1
private void Print()
{
CandleCollection collection = GetCandleCollection();
Class1 c1 = new Class1(collection);
}
Move your CandleCollection variable out of the public method so you can also use it out of this method.
Then, you can instantiate the Class1 variable only once:
private CandleCollection collection = null;
public CandleCollection GetCandleCollection()
{
try
{
collection = SymbolList[cbxSymbol.Text];
}
return collection;
}
private Class1 c1 = new Class1(collection);
private void Print()
{
c1;
}
private void Print2()
{
c1;
}
I have class that draw three types of charts, and i want to update it by function public void GetData(PlotModel PlotModel). The main problem is that every series (AreaSeries,CandleStickSeries,HighLowSeries) has different interfaces. How can i update different types in function public void GetData(PlotModel PlotModel). What should i use Activator? Generic?
I think that something like is bad idea:
public void GetData(PlotModel PlotModel) {
while(true) {
System.Threading.Thread.Sleep(1000);
// Add new Item?
switch(PlotModel.Series.First().ToString()) {
case "OxyPlot.Series.AreaSeries":
Console.WriteLine("AreaSeries");
break;
case "OxyPlot.Series.CandleStickSeries":
Console.WriteLine("CandleStickSeries");
break;
case "OxyPlot.Series.HighLowSeries":
Console.WriteLine("HighLowSeries");
break;
}
}
}
Code:
namespace WpfApplication20 {
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
///
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
DataContext = new PlotClass();
}
}
public class PlotClass {
public PlotModel PlotModel { get; set; }
public PlotClass() {
PlotModel = new PlotModel();
DrawCandleChart(PlotModel);
UpdateChartAsync(PlotModel);
}
public void DrawSimpleChart(PlotModel PlotModel) {
Random rnd = new Random();
LineSeries LS = new LineSeries();
for (int i=0;i<10;i++) {
LS.Points.Add(new DataPoint(i,rnd.NextDouble()));
}
PlotModel.Series.Add(LS);
PlotModel.InvalidatePlot(false);
}
public void DrawCandleChart(PlotModel PlotModel) {
Random rnd = new Random();
CandleStickSeries CSS = new CandleStickSeries();
for (int i=0;i<10;i++) {
CSS.Items.Add(new HighLowItem { Close = rnd.NextDouble(), High = rnd.NextDouble(), Low = rnd.NextDouble(), Open = rnd.NextDouble(), X = i });
}
PlotModel.Series.Add(CSS);
PlotModel.InvalidatePlot(false);
}
public void DrawHighLowChart(PlotModel PlotModel) {
Random rnd = new Random();
HighLowSeries HLS = new HighLowSeries();
for (int i = 0; i < 10; i++) {
HLS.Items.Add(new HighLowItem { Close = rnd.NextDouble(), High = rnd.NextDouble(), Low = rnd.NextDouble(), Open = rnd.NextDouble(), X = i });
}
PlotModel.Series.Add(HLS);
PlotModel.InvalidatePlot(false);
}
public void UpdateChartAsync(PlotModel PlotModel) {
Action<PlotModel> Update = new Action<PlotModel>(GetData);
IAsyncResult result = Update.BeginInvoke(PlotModel, null, null);
}
public void GetData(PlotModel PlotModel) {
while(true) {
System.Threading.Thread.Sleep(1000);
// Add new Item?
}
}
}
}
C# 4 and up offers a nice way of processing situations like this: use cast to dynamic, and call a method with one overload per subtype, like this:
private void Process(AreaSeries arSer) {
...
}
private void Process(CandleStickSeries csSer) {
...
}
private void Process(HighLowSeries hlSer) {
...
}
...
while(true) {
System.Threading.Thread.Sleep(1000);
Process((dynamic)PlotModel.Series.First());
// ^^^^^^^^^
}
The cast to dynamic makes the "magic" happen: C# will examine the run-time type of PlotModel.Series.First(), and dispatch to one of the three Process methods that you supplied.
There is a danger in this approach: if PlotModel.Series.First() happens to not match any of the overloads, you get a run-time exception. The compiler cannot perform static analysis to tell you that your call would not succeed. Consider adding a catch-all method for the common superclass of your plots, too, so that you could handle unexpected sub-types more gracefully.
I am having a problem return a list so that i would be able to save it in a file and then load it so that the weights are saved and be retrieved another time. Sorry for the stupid question but how can i call and save the weights List from the SaveNetwork method , i cant grasp really what i can do to solve the problem. I know that i havent created a new instance of List weights however if i do that i will loose the current weights which are stored in this list.
public class Neuron
{
private double bias; // Bias value.
private double error; // Sum of error.
private double input; // Sum of inputs.
private double gradient = 5; // Steepness of sigmoid curve.
private double learnRate = 0.01; // Learning rate.
private double output = double.MinValue; // Preset value of neuron.
public List<Weight> weights; // Collection of weights to inputs.
public Neuron() { }
public Neuron(Layer inputs, Random rnd)
{
weights = new List<Weight>();
foreach (Neuron input in inputs)
{
Weight w = new Weight();
w.Input = input;
w.Value = rnd.NextDouble() * 2 - 1;
weights.Add(w);
}
}
public static void SaveNetwork(string path)
{
FileStream FS = new FileStream(path, FileMode.Create);
BinaryFormatter BF = new BinaryFormatter();
BF.Serialize(FS,/* The List in this case is List weights ***/ );
FS.Close();
}
public void LoadNetwork(string path)
{
FileStream FS = new FileStream(path, FileMode.Open);
BinaryFormatter BF = new BinaryFormatter();
weights = (List<Weight>)BF.Deserialize(FS);
FS.Close();
}
Update for this--I am using a similar hierarchical structure as the code below which was taken from Dynamic Notions blog which explains how to create a Neural Network. What i want to achieve is that after that the Neural Network has learnt i want to be able to save the List weights so that i would be able to load the weights if the program is stopped in order to skip the training of the network. So basically from the class network i want to access this list which is in Neural Class without creating a new instance in a new method else i will only get an empty List. Hope that its clearer coz i didnt know how to explain it better... Many thanks
public class Network{
//some variables..
[STAThread]
static void Main()
{
new Network();
}
public Network()
{
LoadPatterns();
Initialise();
Train();
Test();
}
private void Train()
{
double error;
do
{
error = 0;
foreach (Pattern pattern in _patterns)
{
double delta = pattern.Output - Activate(pattern);
AdjustWeights(delta);
error += Math.Pow(delta, 2);
}
Console.WriteLine("Iteration {0}\tError {1:0.000}", _iteration, error);
_iteration++;
if (_iteration > _restartAfter) Initialise();
} while (error > 0.1);
}
private void Test()
{
}
// Must be able to call and save the List<Weight> From here
private double Activate(Pattern pattern)
{
}
private void AdjustWeights(double delta)
{
_output.AdjustWeights(delta);
foreach (Neuron neuron in _hidden)
{
neuron.AdjustWeights(_output.ErrorFeedback(neuron));
}
}
private void Initialise()
{
_inputs = new Layer(_inputDims);
_hidden = new Layer(_hiddenDims, _inputs, _rnd);
_output = new Neuron(_hidden, _rnd);
_iteration = 0;
Console.WriteLine("Network Initialised");
}
private void LoadPatterns()
{
}
}
public class Layer : List<Neuron>
{
public Layer(int size)
{
for (int i = 0; i < size; i++)
base.Add(new Neuron());
}
public Layer(int size, Layer layer, Random rnd)
{
for (int i = 0; i < size; i++)
base.Add(new Neuron(layer, rnd)); //this is where Neuron class is instantiated
}
}
public class Neuron
{
//some other vars
private List<Weight> _weights; // This is the list in question.
public Neuron() { }
public Neuron(Layer inputs, Random rnd)
{
_weights = new List<Weight>();
foreach (Neuron input in inputs)
{
Weight w = new Weight();
w.Input = input;
w.Value = rnd.NextDouble() * 2 - 1;
_weights.Add(w);
}
}
}
public class Weight
{
public Neuron Input;
public double Value;
}
Remove the static keyword from SaveNetwork() and use weights where you have your comment.
Hi I'm new to OOP and I need help on a little problem.
I used a collection called Monsters to store 3 types of object. Spiders, Farmers, Gollum(irrelevant).
My collection as an indexer but when I use it to get an object out of the collection the object is typeless but I really need to TypeCast my next opperation.
private void Form1_Load(object sender, EventArgs e)
{
CurrentOpponent Opponent = new CurrentOpponent();
Gollum myGollum = new Gollum();
AngryFarmer myFarmer = new AngryFarmer();
Ugly_Spider mySpider = new Ugly_Spider();
myMonsters.AddGollum(myGollum);
myMonsters.AddFarmer(myFarmer);
myMonsters.AddUgly(mySpider);
progressBar1.Increment(100);
progressBar2.Increment(100);
Monster myCurrentOpponent = Opponent.randomEncounter();
//textBox1.Text = (this is where i need the type for a cast)myCurrentOpponent.name
}
Here is the randomEncounter where i extract the object
class CurrentOpponent
{
public Monster randomEncounter()
{
Random _random = new Random();
int opp = _random.Next(4);
return myMonsters[opp];
}
And finally the indexer wich returns a monster (parent of all 3 monster types)
public Monster this[int xxx]
{
get
{
return (Monster)List[xxx];
}
}
Help would be really appreciated..!!
Thanks in advance
Ideally, AngryFarmer, Ugly_Spider and Gollum should all inherit from Monster:
public class AngryFarmer : Monster
{
// ...
}
// etc.
You could then just use a List<Monster>:
myMonsters = new List<Monster>();
myMonsters.Add(new AngryFarmer()); // works because AngryFarmer is a kind of Monster
This will allow you to use polymorphism.
you need to use interfaces...... IMonster..... IMonster then has a name
then make all your monsters implement IMonster
and just have a List of IMonsters
you may wanna try it by using interfaces also! have a look...
public interface IMonster
{
String Name { get; }
Int32 Health { get; set; }
}
public class Spider : IMonster
{
public Spider()
{
_health = 100;
}
public string Name
{
get { return "Spider"; }
}
private int _health;
public int Health
{
get { return _health; }
set { _health = value; }
}
}
public class Gollum : IMonster
{
public Gollum()
{
_health = 250;
}
public string Name
{
get { return "Gollum"; }
}
private int _health;
public int Health
{
get { return _health; }
set { _health = value; }
}
}
class Program
{
static void Main(string[] args)
{
List<IMonster> monsters = new List<IMonster>()
{
new Gollum(),
new Spider()
};
IMonster randomMonster = GetRandomMonster(monsters);
Console.WriteLine(randomMonster.Name + "/" + randomMonster.Health);
}
private static IMonster GetRandomMonster(List<IMonster> monsters)
{
//Your code for getting a random monster goes here!
throw new NotImplementedException();
}
}
I like very much this approach... Imagine you have an element on your game that initially is not exactly a monster. Say it is a random element on your game that after a given event it becomes a monster that your Hero (say a game like heroes of mighty and magic) have to fight with. If you decided to add this feature long time after you created the game, it would become harmful/difficult/risky to change it, as this element might have already be inheriting from another class. If you were using interfaces you would simply implement it on this entity and it would promptly be capable of behaving like any other IMonster in your game. It means that this random entity would be able to be passed as a param to the method Fight(IHero hero, IMonster monster);
Ideally, AngryFarmer, Ugly_Spider and Gollum should all inherit
from Monster
I have learn your problem like the problem in the Tetris game:
1/ You have Monsters like I have Shapes.
2/ Each kind of Monster have it own properties (Health, Magic Point,...) and behaviours (attack, run, cast spell,..) like the Blocks have properties (color, position, state,..) and
behaviours (go down, rotate right, rotate left,...)
In the scene of the game you want to random a Monster that have the specific properties and behaviours, like I want to random a Shape. If it is your problem you can try my code:
public abstract class CMonster
{
int _HP;
int _MP;
//..and something like this
public int HP
{
get { return this._HP; }
set { this._HP=value;}
}
public int MP
{
get { return this._MP; }
set { this._MP = value; }
}
public abstract void Run();
public abstract void Attach();
public abstract void CastSpell();
}
public class CUgly_Spider : CMonster
{
public CUgly_Spider()
{
this.MP = 100;//your value here
this.HP = 100;//your value here
}
public override void Attach()
{
//your implemetation here
}
public override void Run()
{
//your implemetation here
}
public override void CastSpell()
{
//your implemetation here
}
}
public class CGollum : CMonster
{
public CGollum()
{
this.MP = 100;//your value here
this.HP = 100;//your value here
}
public override void Attach()
{
//your implemetation here
}
public override void Run()
{
//your implemetation here
}
public override void CastSpell()
{
//your implemetation here
}
}
class Test
{
private void InitTheGame()
{
CMonster curMonster=null;
Random rnd = new Random();
//sample random
if ((rnd.Next() % 2) == 0)
{
curMonster = new CGollum();
}
else
{
curMonster = new CUgly_Spider();
}
curMonster.Run();//when (rnd.Next() % 2) == 0 then the Gollum is doing else the Ugly_Spider
curMonster.Attach();//when (rnd.Next() % 2) == 0 then the Gollum is doing else the Ugly_Spider
curMonster.CastSpell();//when (rnd.Next() % 2) == 0 then the Gollum is doing else the Ugly_Spider
}
}
I hope that can help you.