Inheritance error S57036 There is no argument given [duplicate] - c#

This question already has answers here:
C# inheritance and default constructors
(4 answers)
Inheritance with base class constructor with parameters [duplicate]
(2 answers)
Using an abstract class create different classes with user input
(2 answers)
Closed 5 years ago.
I am new to C# and struggling through a tutorial printout. My intention is to inherit properties from the class Rectangle. However I am getting an error I cant resolve. any tips appreciated thank you
Error C57036 There is no argument given that corresponds to the required formal parameter 'a' of 'Rectangle.Rectangle(double, double)'
{
{
//private static void Main(string[] args)
{
Rectangle myRectangle = new Rectangle(23.5, 8.6);
Console.WriteLine(myRectangle.getArea().ToString());
Console.WriteLine(myRectangle.getParimeter().ToString());
Square mySquare = new Square(15);
Console.WriteLine(mySquare.getArea().ToString());
Console.WriteLine(mySquare.getParimeter().ToString());
Console.ReadLine();
}
}
class Rectangle
{
private double length;
private double width;
public Rectangle(double a, double b)
{
length = a;
width = b;
}
public double getArea()
{
return this.length * this.width;
}
public double getParimeter()
{
return 2 * (this.length + this.width);
}
}
class Square : Rectangle
{
public Square(double a)
{
length = a;
}
}
}

Rectangle has no public constructor without arguments, so you need to declare your constructor and call suitable base constructor with arguments:
class Square : Rectangle
{
public Square(double a) : base(a, a)
{
}
}
This also solves the problem of accessing private property in your code.
This should solve compilation error.
However, in your case it looks like you can go right into the most popular Liskov Substitution Principle violation case if you make your class mutable.
In short, in case of mutability you cannot inherit Square from Rectangle even if it sounds logical in real world. It is not possible to implement changing width or height of rectangle so that it behaves correctly in all cases.
Read more about it here:
Is deriving square from rectangle a violation of Liskov's Substitution Principle?
P.S. Please, follow C# naming guidelines. Methods should have an UpperCamelCase name like GetArea or GetPeremiter. When you see a method with name starting with Get, then you probably want it to become a property:
class Rectangle
{
private double _length;
private double _width;
public Rectangle(double a, double b)
{
_length = a;
_width = b;
}
public double Area => this.length * this.width;
public double Perimeter => 2 * (this.length + this.width);
}

Related

Concept regarding Upcasting, Inheritance and setting property using object initializer

The title of the question may seem confusing but bear with me, I'll try to explain the problem as clearly as possible.
So I was just studying about the Liskov substitution principle from a course and the lecturer has given an example showing logical errors we can solve using this principle. Hence, the example shown below is the problem with the logical error.
(Note: Please read the whole question even if you don't know/find out this example has nothing to do with Liskov principle as I've mentioned that above. I've just kept this in question for reference, just in case someone bothers to answer that you're doing it the wrong way)
Rectangle is the parent class
class Rectangle
{
public int Width { get; set; }
public int Height { get; set; }
public Rectangle()
{
}
public Rectangle(int width, int height)
{
Width = width;
Height = height;
}
public override string ToString()
{
return $"{nameof(Width)}: {Width}, {nameof(Height)}: {Height}";
}
}
Square class
class Square : Rectangle
{
public new int Width
{
set { base.Width = base.Height = value; }
}
public new int Height
{
set { base.Width = base.Height = value; }
}
}
Just a simple Caller
private void Caller()
{
Rectangle rc = new Square(); //Upcasting here
rc.Width = 4;
Console.WriteLine($"{rc}"); //Now here the o/p is **Width: 4, Height: 0** which is correct
//But when we use object initializer as shown below
Rectangle rcTwo = new Square { Width = 4 };
Console.WriteLine($"{rcTwo}"); //the o/p is **Width: 4, Height: 4**
}
Now aren't we just initializing the object in a different way? Why is the O/P supposed to differ in that case. I thought that object initializer is just an syntactical sugar when when we to create an object and initialize it's properties in comparison with the traditional approach.
You are right that it's syntactical sugar. But you have to think of the order of operations: assignment is done last, after all the operations on the right of the equals sign. So your second version with initialiser is the same as:
Square square = new Square();
square.Width = 4;
Rectangle rcTwo = square;

Initializing Base Class: declaring a variable twice?

I'm currently reading trough a C# tutorial. Now I came across this:
using System;
namespace RectangleApplication {
class Rectangle {
//member variables
protected double length;
protected double width;
public Rectangle(double l, double w) {
length = l;
width = w;
}
public double GetArea() {
return length * width;
}
public void Display() {
Console.WriteLine("Length: {0}", length);
Console.WriteLine("Width: {0}", width);
Console.WriteLine("Area: {0}", GetArea());
}
}//end class Rectangle
class Tabletop : Rectangle {
private double cost;
public Tabletop(double l, double w) : base(l, w) { }
public double GetCost() {
double cost;
cost = GetArea() * 70;
return cost;
}
public void Display() {
base.Display();
Console.WriteLine("Cost: {0}", GetCost());
}
}
class ExecuteRectangle {
static void Main(string[] args) {
Tabletop t = new Tabletop(4.5, 7.5);
t.Display();
Console.ReadLine();
}
}
}
In the class Tabletop there is cost declared twice. Once as private double cost; and 4 lines later as double cost;
Why is that so?
When removing double cost; the Code still works. When double cost is in the code I can hover over private double cost; and read the message: The field Tabletop.cost is never used". I pretty much can remove either of the cost and the code works fine.
Did they forget to remove one of the declareation or is there a reason behind?
Also, why don't I get an error message like "cost is already defined"?
Here is the Tutorial link
private double cost; is unused and can be removed.
You don't get an error because as John said in the comments, it's in different scopes; one is defined as a field of the class while the other is a local variable. When cost is used, the local variable is accessed. To access the field, this.cost can be used.
class A
{
private int a = 1;
void A()
{
int a = 2;
Console.WriteLine(a); // 2
Console.WriteLine(this.a); // 1
}
}
Note you cannot have multiple local variables with the same name, even in different scopes:
void A()
{
int a = 1;
if(someCondition)
{
int b = 2; // Compiler error: A local variable named 'a' cannot be declared in this scope because it would give a different meaning to 'a', which is already used in a 'parent or current' scope to denote something else
}
}
In fact, in your class Tabletop, the scopes cost is overlapped because there is also a local variable named cost in the method GetCost.
Within the scope of GetCost, when you refer to cost, you are actually referring to the locally scoped object named cost and not the one in the outer scope (the one in the class). When this happens, the cost declared in the outer scope is hidden by the inner scope(in the method).
When defining a variable in a member-scope (in your case within a method) that has the same name as an existing member, you just hide the latter and reference the former.
So in your example:
class Tabletop : Rectangle
{
private double cost;
public Tabletop(double l, double w) : base(l, w) { }
public double GetCost()
{
double cost; // this hides the field
cost = GetArea() * 70;
return cost; // this referts to the variable defined two lines above
}
public void Display()
{
Console.WriteLine("Cost: {0}", cost); // while this refers to the field
}
}
cost from within GetCost will refer to the local variable, while using cost in Display for example will refer to the field.
This is absoluetely fine. However it can yield to confusion and thus unexpected behaviour. This is why some developers tend to use the this-qualifier:
public double GetCost()
{
double cost;
this.cost = GetArea() * 70;
return this.cost;
}
with the qualifier you refer to current instance, making this.cost` an access to your field instead of to the variable.
I think they do forget to remove it.
As why you don't get "cost is already defined" error, it's because the double cost in GetCost() is local (only accessible inside GetCost() method, and will be destroyed from memory after GetCost() method completed), while the private double cost is available to the entire Tabletop class to be accessed and will be kept in memory as long as the Tabletop instance live.
In the class Tabletop there is cost declared twice. Once as private
double cost; and 4 lines later as double cost;
Well private double cost; is a member field for tableTop class whereas other declaration is local to the method body. Why there is a confusion.

C# Objects and Constructors best practices

namespace Area
{
public class Rectangle
{
private double length;
private double width;
public Rectangle() { }
public Rectangle(double length, double width)
{
this.Length = length;
this.Width = width;
}
public double Length
{
get
{
return length;
}
set
{
length = value;
}
}
public double Width
{
get
{
return width;
}
set
{
width = value;
}
}
public double getArea()
{
return width * length;
}
public double getPerimeter()
{
return 2 * width + 2 * length;
}
public double getDiagonal()
{
return Math.Sqrt(Math.Pow(width, 2) + Math.Pow(length, 2));
}
I want to make sure I am using best practices with C# Objects. Please use the above example for reference.
1. Is it necessary that I type the first empty Constructor? In class the Instructor always did on each program but never really gave an answer as to why.
public Rectangle() { }
2. Inside my Custom Constructor Visual Studio generates it like this:
this.Length = length;
I know that the "this" keyword is not necessary the way it is typed, but in class the instructor sometimes changed it to lowercase like this:
this.length = length;
But sometimes he didn't change it. Which way is best practices?
And is the left side the actual Property? And then the right side is the field?
So it is, Property equals field?
3. And finally, in this case cant I just type my properties as:
public string Length { get; set; }
instead of the way Visual Studio generates with the return and value.
Sorry for the long post, I am tired of getting different answers at school and want one final answer on this, thanks.
I would suggest that your class look like this:
public class Rectangle
{
public Rectangle(double length, double width)
{
this.Length = length;
this.Width = width;
}
public double Length { get; set; }
public double Width { get; set; }
public double Area { get { return this.Width * this.Length; } }
public double Perimeter { get { return 2.0 * (this.Width + this.Length); } }
public double Diagonal { get { return Math.Sqrt(Math.Pow(this.Width, 2.0) + Math.Pow(this.Length, 2.0)); } }
}
See here for why you might want a blank constructor. To summarize, adding a non blank constructor will stop the compiler from generating a blank one for you (the compiler assumes that if you wanted it, you would have defined it with the other constructors you wrote). Some things, like serialization, will not work without a blank constructor, so that's a reason you might want to add one.
In my career, I've mostly seen people avoid using this in constructors. Maybe avoid isn't the right word, but unless it's unclear, they just didn't bother to put it there. This is probably too minor an issue to lose any sleep over.
UPDATE based on some of your comments
When you write
public Rectangle(double length, double width)
{
Length = length; //parameter length assigned to field length by virtue of property Length
}
you are assigning the parameter length to the property Length, which itself assigns the passed in value to the length private field. Since C# is case sensitive, Length and length aren't confused in any scenario, and you don't need to specify the this keyword.
Inside a method with a parameter called length, the language is assuming that you are referring to the parameter of the method when you type length. So if you try to do something like this:
public Rectangle(double length, double width)
{
length = length; //warning: Assignment made to same variable; did you mean to assign to something else
}
The compiler doesn't try and assume that you are assigning the property to the field, and this is just assigning the length parameter to itself. In this case, you would use the this keyword to tell the compiler that you want to assign the parameter length to the private field length, like this:
public Rectangle(double length, double width)
{
this.length = length; //no warning
}
END UPDATE
Yes, you could declare the property as just Property {get;set;}. This feature is only from C# 3.0 and is called auto-implemented properties (see this link). Before that you had to provide the implementation yourself.
I changed my class to this:
public class Rectangle
{
public Rectangle(double length, double width)
{
Length = length;
Width = width;
}
public double Length { get; set; }
public double Width { get; set; }
public double getArea()
{
return Width * Length;
}
public double getPerimeter()
{
return 2 * Width + 2 * Length;
}
public double getDiagonal()
{
return Math.Sqrt(Math.Pow(Width, 2) + Math.Pow(Length, 2));
}
}
If anyone has any other feedback on anything above that you recommend to change please give it, I catch on very fast and want to learn the correct way.

C# Accessing values of a derived class in an array of the base class

This is not exactly what I am working with but I hope it makes a clear example:
public abstract class Shape
{
public int Area;
public int Perimeter;
public class Polygon : Shape
{
public int Sides;
public Polygon(int a, int p, int s){
Area = a;
Perimeter = p;
Sides = s;
}
}
public class Circle : Shape
{
public int Radius;
public Circle(int r){
Area = 3.14*r*r;
Perimeter = 6.28*r;
Radius = r;
}
}
}
In the main function I would have something like this:
Shape[] ThisArray = new Shape[5];
ThisArray[0] = new Shape.Circle(5);
ThisArray[1] = new Shape.Polygon(25,20,4);
My problem is that when I deal with ThisArray, I can't access values other than Area and Perimeter. For example:
if (ThisArray[0].Area > 10)
//This statement will be executed
if (ThisArray[1].Sides == 4)
//This will not compile
How can I access Sides from ThisArray[1]? I could access it if I did something like
Shape.Polygon RandomSquare = new Shape.Polygon(25,20,4) but not if it is in an array of shapes.
If I recall correctly this could be accomplished in C++ by doing something like
Polygon->ThisArray[1].Sides (I forget what this is called) but I do not know how do this in C#
If I can't do what I am trying to do, how can I circumvent this problem?
Thank you for reading through what I intended to be short, any help is appreciated.
You should use casting:
(ThisArray[1] as Shape.Polygon).Sides
Note that you should make sure the underlying object instance actually IS a Polygon, otherwise this will raise an exception. You can do this by using something like:
if(ThisArray[1] is Shape.Polygon){
(ThisArray[1] as Shape.Polygon).Sides
}

How can I store different objects in a single list

I have two classes an Arc class and a Line class
public class Arc
{
protected double startx;
protected double starty;
protected double endx;
protected double endy;
protected double radius;
public Arc(){}
}
public class Line
{
protected double startx;
protected double starty;
protected double endx;
protected double endy;
protected double length;
public Line(){}
}
But I want to store arcs and lines in the same list, so I tried an interface like this
public interface Entity
{
double StartX();
double StratY();
double EndX();
double EndY();
}
Then I added the appropriate methods to each class and added the code to use the interface. Now I can add both types of objects to a list, but I want to get the length from a line object and don't want to add a length method to the arc or the interface. Is my only option to cast the line object back to a line object like this?
List<Entity> entities = new List<Entity>();
entities.Add(new Line(10,10,5,5));
Line myLine = (Line)Entities[0]
double length = myLine.Length();
*Assuming I have all the proper methods in the line class.
Or is there a better/different way to do this?
If you're in .NET 3.5 or above, you can make this a bit less ugly this way:
List<Entity> entities = new List<Entity>();
// add some lines and some arcs
var lines = entities.OfType<Line>();
Then you just loop through lines, which will contain all the lines (strongly-typed as Lines) and nothing else.
I'm not saying this is the best approach; I'm only saying this is one way to do what you're doing. I agree with Shmoopty that it's an architecture problem.
Since Arc and Line share data (startx and some other fields), I suggest you use a common abstract class as parent class rather than an interface. For example, Figure.
The cast is okay, although I would rather recommend:
Line myLine = Entities[0] as Line;
It will return null if Entities[0] cannot be converted to a Line, rather than throwing an exception. You will be able to check whether myLine is null afterward.
Yes, it is the only way, given your constraints.
I would suggest adding length to the interface (since arc does have a length).
The formula can be found here.
Or alternatively you could add the method to the interface, and have it throw a NotImplementedException.
Have the interface implement a "Size" property (or call it "magnitue", or "Range". . .)
This maps to the Arc's radius, and to the lines length.
Then you can get Entity.Size.
It depends how you want to treat Arcs when you get them out of the list. If you try and cast an Arc to a Line you will get a runtime error, so for starters you should check if the Entity you're working with is a Line.
One way to handle Arcs is to use the Null Object Pattern. It might make sense to add a length method to Arc that returns 0. That way the code that retrieves objects from the list doesn't have to care what kind they are.
List<object> could work depending on what you intend to do with the list. If you have a set number of types you are working with
Lets say I have a list of properties from different classes I need to access. They are all stored in a List of string in format Model.Property.
Then I have a list of objects in a List of objects.
foreach(object model in models)
{
Assembly assembly = Assembly.GetExecutingAssembly();
Type type = assembly.GetType(model.GetType().FullName);
foreach (string match in matches)
{
string property = match.Replace($"{model.GetType().Name}.", "");
if (match == $"{model.GetType().Name}.{property}")
{
PropertyInfo prop = type.GetProperty(property);
string value = prop.GetValue(model).ToString();
}
}
}
Or is there a better/different way to
do this?
If your objects descend from a common class, then you can store them in the same collection. In order to do anything useful with your objects without throwing away type safety, you'd need to implement the visitor pattern:
public interface EntityVisitor
{
void Visit(Arc arc);
void Visit(Line line);
}
public abstract class Entity
{
public abstract void Accept(EntityVisitor visitor);
}
public class Arc : Entity
{
protected double startx;
protected double starty;
protected double endx;
protected double endy;
protected double radius;
public override void Accept(EntityVisitor visitor)
{
visitor.Visit(this);
}
}
public class Line : Entity
{
protected double startx;
protected double starty;
protected double endx;
protected double endy;
protected double length;
public override void Accept(EntityVisitor visitor)
{
visitor.Visit(this);
}
}
Once that's in place, you create an instance of EntityVisitor whenever you need to do something useful with your list:
class EntityTypeCounter : EntityVisitor
{
public int TotalLines { get; private set; }
public int TotalArcs { get; private set; }
#region EntityVisitor Members
public void Visit(Arc arc) { TotalArcs++; }
public void Visit(Line line) { TotalLines++; }
#endregion
}
class Program
{
static void Main(string[] args)
{
Entity[] entities = new Entity[] { new Arc(), new Line(), new Arc(), new Arc(), new Line() };
EntityTypeCounter counter = entities.Aggregate(
new EntityTypeCounter(),
(acc, item) => { item.Accept(acc); return acc; });
Console.WriteLine("TotalLines: {0}", counter.TotalLines);
Console.WriteLine("TotalArcs: {0}", counter.TotalArcs);
}
}
And for what its worth, if your open to trying new languages, then F#'s tagged unions + pattern matching are a handy alternative to the visitor pattern.

Categories

Resources