Problem:
// Create an Image class with two properties, Width and Height
// Whenever Width is updated, Height should be updated in proportion
// Tips: avoid below 2 traps
// 1. Updating Width and Height triggers an infinite dead loop
// 2. The dependent update triggered incorrectly by the object initialization or copy
Solution 1:
class Image1
{
//private bool dependentUpdateLock;
int _width;
public int Width
{
get => _width;
set
{
if (_width != 0)
_height = (int)Math.Round(1.0 * value * _height / _width);
_width = value;
}
}
int _height;
public int Height
{
get => _height;
set
{
if (_height != 0)
_width = (int)Math.Round(1.0 * value * _width / _height);
_height = value;
}
}
public Image1(int w, int h)
{
_width = w;
_height = h;
}
public void Display()
{
Console.WriteLine(string.Format("W=={0}, H=={1}", Width, Height));
}
}
Solution 2:
class Image2
{
public int Width { get; private set; }
public int Height { get; private set; }
public void SetWidthAndHeight(int w, int h)
{
Width = w;
Height = h;
}
public int NewWidthFromNewHeight(int newHeight)
{
return Height == 0 ? Width : (int)Math.Round(1.0 * newHeight * Width / Height);
}
public int NewHeightFromNewWidth(int newWidth)
{
return Width == 0 ? Height : (int)Math.Round(1.0 * newWidth * Height / Width);
}
public Image2(int w, int h)
{
SetWidthAndHeight(w, h);
}
public void Display()
{
Console.WriteLine(string.Format("W=={0}, H=={1}", Width, Height));
}
public Image2 Clone()
{
return new Image2(Width, Height);
}
}
Result in comparison:
void Test_Dependent_Update()
{
Image1 image1A = new Image1(10, 10);
Console.WriteLine("A:");
image1A.Display();
Image1 image1B = new Image1(15, 5);
Console.WriteLine("B:");
image1B.Display();
image1A = image1B;
Console.WriteLine("A = B:");
image1A.Display();
image1A.Width = 10;
Console.WriteLine("A after W explicitly set:");
image1A.Display();
image1A.Height = 10;
Console.WriteLine("A after H explicitly set:");
image1A.Display();
Console.WriteLine("================");
Image2 image2A = new Image2(10, 10);
Console.WriteLine("A:");
image2A.Display();
Image2 image2B = new Image2(15, 5);
Console.WriteLine("B:");
image2B.Display();
image2A = image2B.Clone();
Console.WriteLine("A = B.Clone():");
image2A.Display();
image2A.SetWidthAndHeight(10, 10);
Console.WriteLine("A after W&H set separately:");
image2A.Display();
image2B.SetWidthAndHeight(10, image2B.NewHeightFromNewWidth(10));
Console.WriteLine("B after W&H set in relation:");
image2B.Display();
}
Output:
A:
W==10, H==10
B:
W==15, H==5
A = B:
W==15, H==5
A after W explicitly set:
W==10, H==3
A after H explicitly set:
W==33, H==10
================
A:
W==10, H==10
B:
W==15, H==5
A = B.Clone():
W==15, H==5
A after W&H set separately:
W==10, H==10
B after W&H set in relation:
W==10, H==3