I have four errors that I am struggling with.
In the WriteLine block meant to print out the areas of the shapes, both places where the variable 'area' appears give the error message: "The name 'area' does not exist in the current context". The second problem is within the class Rectangle : GeometricFigure for 'ComputeArea', the error reads "'Rectangle.ComputeArea()' hides inherited member 'GeometricFigure.ComputeArea()'. Use the new keyword if hiding was intended." The last error is within the class Triangle : GeometricFigure and concerns 'Triangle' in the 'public Triangle(int x, int y)' expression. The error message reads "'Rectangle.ComputeArea()' hides inherited member 'GeometricFigure.ComputeArea()'. Use the new keyword if hiding was intended.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Console;
namespace ShapesDemo
{
class Program
{
static void Main(string[] args)
{
Rectangle rec = new Rectangle(8, 10);
Square squ = new Square(11, 12);
Triangle tri = new Triangle(10, 20);
Console.WriteLine("Computed area is {0}" + "\n\n" + "Computed Triangle is: {1}" + "\n",
squ.ComputeArea(area), tri.ComputeArea(area));
}
}
abstract class GeometricFigure
{
public GeometricFigure(decimal sideA, decimal sideB)
{
this.height = sideA;
this.width = sideB;
}
protected decimal area;
protected decimal width;
protected decimal height;
public decimal Height
{
get
{
return height;
}
set
{
height = value;
ComputeArea();
}
}
public decimal Width
{
get
{
return width;
}
set { width = value; }
}
public decimal Area
{
get { return area; }
set { area = value; }
}
public void ComputeArea()
{
}
}
class Rectangle : GeometricFigure
{
public Rectangle(decimal sideA, decimal sideB) : base(sideA, sideB)
{
}
public void ComputeArea()
{
area = width * height;
WriteLine("The Area is" + width.ToString(), height.ToString());
}
static void Display(Rectangle rec)
{
}
}
class Square : GeometricFigure
{
static void Display(Square squ)
{
}
public Square(decimal sideA, decimal sideB) : base(sideA, sideA)
{
}
}
class Triangle : GeometricFigure
{
static void Display(Triangle tri)
{
}
public Triangle(int x, int y)
{
this.Width = x;
this.Height = y;
}
}
}
The name area doesn't exist so you can't use it. The Main() method doesn't have access to area. I think what you are trying to do is:
class Program
{
static void Main(string[] args)
{
Rectangle rec = new Rectangle(8, 10);
Square squ = new Square(11, 12);
squ.ComputeArea();
Triangle tri = new Triangle(10, 20);
tri.ComputeArea();
Console.WriteLine("Computed area is {0}" + "\n\n" + "Computed Triangle is: {1}" + "\n",
squ.Area, tri.Area);
Console.ReadLine();
}
}
But you have a bigger design problem as well. Using GeometricFigure base class is going to give you a lot of problems. I would get rig of it completely or use an interface instead. Also your Triangle needs to be:
public Triangle(decimal sideA, decimal sideB) : base(sideA, sideA)
{
this.Width = sideA;
this.Height = sideB;
}
The Microsoft docs have a good example of what your are attempting to accomplish here, generally you want to:
Abstract what is common(in this case its computing the area)
Specify what is not common in your concretes
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/how-to-define-abstract-properties
Related
I have created an interface and then derived a class from it:
public interface Ishape
{
void draw();
int Number { get; set; }
}
class Circle : Ishape
{
public Circle(int a)
{
number = a;
}
public void draw()
{
Console.WriteLine("Circle.");
}
private int number;
public int Number
{
get
{
return number;
}
set
{
if (value < -5)
number = -5;
}
}
public int GetNumber()
{
return number;
}
}
class Program
{
static void Main(string[] args)
{
Circle a1 = new Circle(-6);
Console.WriteLine(a1.GetNumber());
Console.ReadLine();
}
}
As you can see, there is an autoproperty in the interface. I then decided to create a property in the new class that derived from the interface that would set the variable "number" to -5 if the value is less than -5. For some reason, the property does not seem to be working. Using the constructor, I set the value of the variable to -6, and the property did not change the value to -5. Why?
This is because you are setting number = a and not Number = a in your constructor. Try this:
public Circle(int a)
{
Number = a;
}
Your Number Property is never actually set.
In your Circle constructor, change number to Number.
public Circle(int a)
{
Number = a;
}
Also, if you intend to use GetNumber as your publicly available get (and nothing more), then I would advise that you change the access modifier for your Number property in your Circle class.
I'm making a game in C#. I created a base class Shape and seven other classes (Shape1, Shape2, ...) that inherit from Shape. In my main program I keep track of the shape currently in play by using
Shape Current;
Then I randomise its value to be equal to one of the shapes, for example:
Current = new Shape1()
The problem is, after I randomise I want to draw the shape with
Current.Draw()
Each shape has its own Draw function, and I want it to use that function specificly, and not the function in Shape. How can I do that?
The concept you are describing is called polymorphism (treating different object types as one).
In C#, you do this via the virtual, abstract and override keywords. In the base class, you mark the polymorphic method as either virtual or abstract, with the difference being abstract methods must be defined by derived classes:
public abstract void Draw();
Note that virtual methods must define a body, while abstract methods must not. Then in the derived class you define the same method with the override keyword:
public override void Draw()
{
//whatever implementation
}
For far more information, see MSDN
I must say #BradleyDotNet explained it very well, I'm just adding a practical example that may help to clarify the use of it.
Notice how I used all virtual, abstract and override keywords.
using System;
namespace ShapeExample
{
class Program
{
public static void Main(string[] args)
{
for (int i = 0; i < 20; i++)
{
var shape = GetRandomShape();
shape.Draw();
}
}
public static Random Random = new Random();
public static Shape GetRandomShape()
{
var d = Random.Next(3);
switch (d)
{
case 1:
return new Shape1();
case 2:
return new Shape2();
default:
return new Shape3();
}
}
}
public abstract class Shape
{
public virtual void Draw()
{
//Console.WriteLine("General Shape");
Console.WriteLine(" _");
Console.WriteLine(" / \\ ");
Console.WriteLine("/___\\");
}
}
public class Shape1 : Shape
{
public override void Draw()
{
//Console.WriteLine("I want a square instead");
Console.WriteLine(" ____");
Console.WriteLine("| |");
Console.WriteLine("|____|");
}
}
public class Shape2 : Shape
{
public override void Draw()
{
//Console.WriteLine("I want a complicated circle instead");
double r = 3.0;
double r_in = r - 0.4;
double r_out = r + 0.4;
for (double y = r; y >= -r; --y)
{
for (double x = -r; x < r_out; x += 0.5)
{
double value = x * x + y * y;
if (value >= r_in * r_in && value <= r_out * r_out)
{
Console.Write('*');
}
else
{
Console.Write(' ');
}
}
Console.WriteLine();
}
}
}
public class Shape3 : Shape
{
//I don't care how I look like, I'm using the regular shape drawing.
//but I have some particular info that is not part of a regular Shape
public int ParticularField { get; }
public Shape3()
{
ParticularField = -100;
}
}
}
So basically i am trying to do a project in a windows form where i determine the number of vertices and it assigns each vertex a co-ordinate and outputs it on another form. for some reason it isn't working properly could anyone take a look?
MainForm
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace assignment
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
public List<Vertex> vertexList = new List<Vertex>();
private void Exit_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void Create_Click(object sender, EventArgs e)
{
int vertices = 0, edges = 0;
try
{
vertices = (int)Convert.ToInt32(txtVertices.Text);
edges = (int)Convert.ToInt32(txtEdges.Text);
if (vertices < 0)
MessageBox.Show("Vertices cannot be less than 0", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
else
if (edges < 0 || edges > 1)
MessageBox.Show("Edges have to be 0..1", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
else
{
//MessageBox.Show("Graph successfully created", "Info", MessageBoxButtons.OK, MessageBoxIcon.Information);
for (int i = 0; i < vertices; i++)
{
Vertex vertex = new Vertex();
Vertex vertex1 = vertex.CreateVertex(vertices);
vertexList.Add(vertex1);
}
VertexDisplay display = new VertexDisplay();
display.DisplayVertices(vertexList);
display.Show();
}
}
catch(Exception x)
{
MessageBox.Show("Vertices or edges Cannot be left out", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
Vertex Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace assignment
{
public class Vertex
{
public int x;
public int y;
public int z;
public int vertexID;
public int X
{
get { return x; }
set { x = value; }
}
public int Y
{
get { return y; }
set { y = value; }
}
public int Z
{
get { return z; }
set { z = value; }
}
public int VertexID
{
get { return vertexID; }
set { vertexID = value; }
}
public Vertex CreateVertex(int noOfVertex)
{
Random rnd = new Random();
Vertex vertex = new Vertex(x, y, z, vertexID);
MainForm mainform = new MainForm();
vertex.x = rnd.Next(0, 100);
vertex.y = rnd.Next(0, 100);
vertex.z = rnd.Next(0, 100);
vertex.vertexID = rnd.Next(0, noOfVertex);
return(vertex);
}
public Vertex()
{
}
public Vertex(int x, int y, int z, int id)
{
this.x = x;
this.y = y;
this.z = z;
this.vertexID = id;
}
}
}
Display From
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace assignment
{
public partial class VertexDisplay : Form
{
public VertexDisplay()
{
InitializeComponent();
MainForm mainform = new MainForm();
DisplayVertices(mainform.vertexList);
}
public void DisplayVertices(List<Vertex>vertexList)
{
int x, y, z, id;
foreach(Vertex vertexDetails in vertexList)
{
x = vertexDetails.X;
y = vertexDetails.Y;
z = vertexDetails.Z;
id = vertexDetails.VertexID;
txtVertexDisplay.Text = string.Join(Environment.NewLine, " ID: " + id + " x: " + x + " y: " + y + " z: " + z);
}
}
}
}
You are setting txtVertexDisplay.Text property inside a Foreach loop so You are setting this each time loop iterate. Its not concatenation it's always beeing set to be exactly something. If You want to concatenate Your output - use some temporary string property and += operator. See below:
public void DisplayVertices(List<Vertex>vertexList)
{
String displayText = string.Empty;
int x, y, z, id;
foreach(Vertex vertexDetails in vertexList)
{
x = vertexDetails.X;
y = vertexDetails.Y;
z = vertexDetails.Z;
id = vertexDetails.VertexID;
displayText += string.Join(Environment.NewLine, " ID: " + id + " x: " + x + " y: " + y + " z: " + z);
}
txtVertexDisplay.Text = displayText;
}
I am currently writing a program which reads data in from a text file. The problem I am currently having is that the CompareTo method below is coming up with the error System.StackOverflowException was unhandled and saying "Make sure you don't have an infinite loop or infinite recursion. This error appears on the line return name.CompareTo(temp.name);.
The whole class is as follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Country
{
public class Country : IComparable
{
// Country Properties
private String name;
private float gdpGrowth;
private float inflation;
private float tradeBalance;
private float hdiRanking;
private LinkedList<String> tradePartners;
//Constructor
public Country(String name, float gdpGrowth, float inflation, float tradeBalance, float hdiRanking, LinkedList<String> tradePartners)
{
this.name = name;
this.gdpGrowth = gdpGrowth;
this.inflation = inflation;
this.tradeBalance = tradeBalance;
this.hdiRanking = hdiRanking;
this.tradePartners = tradePartners;
}
public String Name
{
set { this.name = value; }
get { return name; }
}
public float GdpGrowth
{
set { this.gdpGrowth = value; }
get { return gdpGrowth; }
}
public float Inflation
{
set { this.inflation = value; }
get { return inflation; }
}
public float TradeBalance
{
set { this.tradeBalance = value; }
get { return tradeBalance; }
}
public float HdiRankings
{
set { this.hdiRanking = value; }
get { return hdiRanking; }
}
public LinkedList<String> TradePartners
{
set { this.tradePartners = value; }
get { return tradePartners; }
}
public override string ToString()
{
return name + ", " + gdpGrowth + ", " + inflation + ", " + tradeBalance + ", " + hdiRanking + ", " + tradePartners;
}
public int CompareTo(object other)
{
Country temp = (Country)other;
return name.CompareTo(temp.name);
}
}
}
The class which is calling the country class is...
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace Country
{
public partial class Form1 : Form
{
private AVLTree<Country> countryTree = new AVLTree<Country>();
public Form1()
{
InitializeComponent();
}
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
// array to stroe each line of the file
String[] Lines = new string[1000];
String[] tempPartners = new string[1000];
int count = 0;
// Store each line of the file in the eachLine array
Lines = File.ReadAllLines("countries.csv");
foreach (String line in Lines)
{
if (count == 0)
{
count++;
}
else
{
// array to hold info
String[] info = new string[5];
//splits the countries
info = line.Split(',');
// split trade partners and puts in array
tempPartners = info[5].Split(';', '[', ']');
// insert current instance of country into AVL Tree
countryTree.InsertItem(new Country(info[0], float.Parse(info[1]),
float.Parse(info[2]), float.Parse(info[3]), float.Parse(info[4]), new LinkedList<String>(tempPartners)));
// create seperator
string seperator = ", ";
// stroe array
string partners = string.Join(seperator, tempPartners);
// remove first comma
partners = partners.Substring(1, partners.Length - 1);
//remove last comma
partners = partners.Remove(partners.Length - 2);
//pass in information from file into grid view
dataGridView1.Rows.Add(info[0], info[1], info[2], info[3], info[4], partners);
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
You've got infinite recursion going here. CompareTo makes a recursive call but doesn't terminate due to the lack of a base case, so the recursive stack grows infinite. No actual comparison takes place either. What integer values do you want this to return, and under what conditions?
Perhaps as CyberDude said, you're really trying to use String.Compare(name, temp.name)?
I just made a class Shapes and an other 2 classes ('Triangle' & 'Square') which inherit from 'Shapes'.
public class Shapes
{
private int sides;
}
public class Triangle : Shapes
{
public void init()
{
int sides = 3;
throw new System.NotImplementedException();
}
}
public class Square : Shapes
{
public void init()
{
int sides = 4;
throw new System.NotImplementedException();
}
}
Code is designed using Classdiagram
Question: How should I call the class so that it shows how many sides does a shape has?
Thanks
You need a protected member sides which is used within the init-section of every shape:
public class Shapes
{
protected readonly int sides;
public int NumberOfSides { get { return sides; } }
}
public class Triangle : Shapes
{
public Triangle()
{
this.sides = 3;
}
}
public class Square : Shapes
{
public Square()
{
this.sides = 4;
}
}
As Farhad Jabiyev mentioned using constructors is the usual way to initialize a new instance (see my code above)
Now when you call Shape#NumberOfSides you get 3 for Triangle and 4 for Square:
Shape square = new Square();
int number = square.NumberOfSides();
You need to add a property on the class that has an accessor like this
public class Shapes
{
private int sides;
public int NumberOfSides { get { return sides; } }
}
Then you can go mySquare.NumberOfSides