Lab: Static#
Objective#
In this lab, we will be working with static members in C#. Specifically, we will modify a Rectangle
class to track the number of instances created and to calculate the average area of all created rectangles.
Understanding static members and classes will help us better appreciate why they should be avoided.
Provided Code#
Carefully review the provided code. Notice how, currently, there is no mechanism to track the total number of Rectangle
instances or perform operations across all instances.
class Rectangle
{
public double Width { get; set; }
public double Height { get; set; }
public double Area => Width * Height;
public Rectangle(double width, double height)
{
Width = width;
Height = height;
}
}
The Rectangle
class provided includes properties for Width
and Height
, a constructor to set those properties, and a computed, read-only property called Area
that computes the area of the rectangle.
Instructions#
Step 1: Introduce a Static Property#
First, introduce add a static property to the Rectangle
class to keep track of how many rectangles have been instantiated. You can call it Count
and it should have a public
get
accessor but a private
set
accessor.
For each Rectangle
instance created, increment the static counter field. This will allow us to keep track of how many rectangles have been created.
Here’s what the code should behave like:
new Rectangle(20, 10);
new Rectangle(2, 5);
new Rectangle(10, 12);
Console.WriteLine(Rectangle.Count);
3
🤔 Reflection
Can the class Rectangle
be marked as static
? Why or why not?
Step 2: Static Constructor Message#
Next, add a static constructor in the Rectangle
class that writes a message to the console indicating that the rectangle counter is active.
Here’s what the code should behave like:
new Rectangle(20, 10);
new Rectangle(2, 5);
new Rectangle(110, 12);
Console.WriteLine(Rectangle.Count);
Rectangle counter is now active.
3
Step 3: Array of Rectangles#
Introduce another static field of type Rectangle[]
. This static field should be an array that always contains all Rectangle
s that have been created. You should achieve this by updating the constructor so that it adds the new Rectangle
instance to this array.
This should also allow you to refactor the static property called Count
, into a computed, read-only property who’s value is computed from the array.
The code should behave like this:
new Rectangle(20, 10);
new Rectangle(2, 5);
new Rectangle(10, 12);
foreach (Rectangle rect in Rectangle.Instances)
Console.WriteLine($"{rect.Width}x{rect.Height} = {rect.Area}");
Rectangle counter is now active.
20x10 = 200
2x5 = 10
10x12 = 120
Step 4: Computed Read-Only Static Property#
Implement a static property called AverageArea
that computes the average area of all rectangles stored in the static array.
The code should behave like this:
new Rectangle(20, 10);
new Rectangle(2, 5);
new Rectangle(10, 12);
Console.WriteLine(Rectangle.AverageArea);
110
Challenge#
Consider how you would write a program to achieve similar functionality without using static members. Before tackling this problem, make sure you understand Object Composition and how it can be used to manage state and behavior among objects.
🤔 Reflection
Reflect on how the use of static members changes the design and functionality of our Rectangle
class. What are the limitations and benefits of using static members in this scenario? Can you think of any potential issues with using a static array to store instances?
Hint
To redesigning the solution without static members, consider how an instance of another class might manage multiple Rectangle
instances and perform the necessary calculations.