Bläddra i källkod

Add missing IEquatable interfaces to structs. Standardize parsing error messages. Fix two instances of boxing in hash code.

Dariusz Komosinski 6 år sedan
förälder
incheckning
cb663f98b1

+ 55 - 13
src/Avalonia.Visuals/CornerRadius.cs

@@ -8,7 +8,10 @@ using Avalonia.Utilities;
 
 namespace Avalonia
 {
-    public struct CornerRadius
+    /// <summary>
+    /// Represents the radii of a rectangle's corners.
+    /// </summary>
+    public readonly struct CornerRadius : IEquatable<CornerRadius>
     {
         static CornerRadius()
         {
@@ -33,20 +36,60 @@ namespace Avalonia
             BottomLeft = bottomLeft;
         }
 
+        /// <summary>
+        /// Radius of the top left corner.
+        /// </summary>
         public double TopLeft { get; }
+
+        /// <summary>
+        /// Radius of the top right corner.
+        /// </summary>
         public double TopRight { get; }
+
+        /// <summary>
+        /// Radius of the bottom right corner.
+        /// </summary>
         public double BottomRight { get; }
+
+        /// <summary>
+        /// Radius of the bottom left corner.
+        /// </summary>
         public double BottomLeft { get; }
+
+        /// <summary>
+        /// Gets a value indicating whether all corner radii are set to 0.
+        /// </summary>
         public bool IsEmpty => TopLeft.Equals(0) && IsUniform;
+
+        /// <summary>
+        /// Gets a value indicating whether all corner radii are equal.
+        /// </summary>
         public bool IsUniform => TopLeft.Equals(TopRight) && BottomLeft.Equals(BottomRight) && TopRight.Equals(BottomRight);
 
+        /// <summary>
+        /// Returns a boolean indicating whether the corner radius is equal to the other given corner radius.
+        /// </summary>
+        /// <param name="other">The other corner radius to test equality against.</param>
+        /// <returns>True if this corner radius is equal to other; False otherwise.</returns>
+        public bool Equals(CornerRadius other)
+        {
+            // ReSharper disable CompareOfFloatsByEqualityOperator
+            return TopLeft == other.TopLeft &&
+                   
+                   TopRight == other.TopRight &&
+                   BottomRight == other.BottomRight &&
+                   BottomLeft == other.BottomLeft;
+            // ReSharper restore CompareOfFloatsByEqualityOperator
+        }
+
         public override bool Equals(object obj)
         {
-            if (obj is CornerRadius)
+            if (!(obj is CornerRadius))
             {
-                return this == (CornerRadius)obj;
+                return false;
             }
-            return false;
+
+            return Equals((CornerRadius)obj);
         }
 
         public override int GetHashCode()
@@ -61,7 +104,9 @@ namespace Avalonia
 
         public static CornerRadius Parse(string s)
         {
-            using (var tokenizer = new StringTokenizer(s, CultureInfo.InvariantCulture, exceptionMessage: "Invalid Thickness"))
+            const string exceptionMessage = "Invalid CornerRadius.";
+
+            using (var tokenizer = new StringTokenizer(s, CultureInfo.InvariantCulture, exceptionMessage))
             {
                 if (tokenizer.TryReadDouble(out var a))
                 {
@@ -78,21 +123,18 @@ namespace Avalonia
                     return new CornerRadius(a);
                 }
 
-                throw new FormatException("Invalid CornerRadius.");
+                throw new FormatException(exceptionMessage);
             }
         }
 
-        public static bool operator ==(CornerRadius cr1, CornerRadius cr2)
+        public static bool operator ==(CornerRadius left, CornerRadius right)
         {
-            return cr1.TopLeft.Equals(cr2.TopLeft)
-                   && cr1.TopRight.Equals(cr2.TopRight)
-                   && cr1.BottomRight.Equals(cr2.BottomRight)
-                   && cr1.BottomLeft.Equals(cr2.BottomLeft);
+            return left.Equals(right);
         }
 
-        public static bool operator !=(CornerRadius cr1, CornerRadius cr2)
+        public static bool operator !=(CornerRadius left, CornerRadius right)
         {
-            return !(cr1 == cr2);
+            return !(left == right);
         }
     }
 }

+ 4 - 2
src/Avalonia.Visuals/Matrix.cs

@@ -10,7 +10,7 @@ namespace Avalonia
     /// <summary>
     /// A 2x3 matrix.
     /// </summary>
-    public readonly struct Matrix
+    public readonly struct Matrix : IEquatable<Matrix>
     {
         private readonly double _m11;
         private readonly double _m12;
@@ -235,12 +235,14 @@ namespace Avalonia
         /// <returns>True if this matrix is equal to other; False otherwise.</returns>
         public bool Equals(Matrix other)
         {
+            // ReSharper disable CompareOfFloatsByEqualityOperator
             return _m11 == other.M11 &&
                    _m12 == other.M12 &&
                    _m21 == other.M21 &&
                    _m22 == other.M22 &&
                    _m31 == other.M31 &&
                    _m32 == other.M32;
+            // ReSharper restore CompareOfFloatsByEqualityOperator
         }
 
         /// <summary>
@@ -316,7 +318,7 @@ namespace Avalonia
         /// <returns>The <see cref="Matrix"/>.</returns>
         public static Matrix Parse(string s)
         {
-            using (var tokenizer = new StringTokenizer(s, CultureInfo.InvariantCulture, exceptionMessage: "Invalid Matrix"))
+            using (var tokenizer = new StringTokenizer(s, CultureInfo.InvariantCulture, exceptionMessage: "Invalid Matrix."))
             {
                 return new Matrix(
                     tokenizer.ReadDouble(),

+ 16 - 4
src/Avalonia.Visuals/Media/PixelPoint.cs

@@ -10,7 +10,7 @@ namespace Avalonia
     /// <summary>
     /// Represents a point in device pixels.
     /// </summary>
-    public readonly struct PixelPoint
+    public readonly struct PixelPoint : IEquatable<PixelPoint>
     {
         /// <summary>
         /// A point representing 0,0.
@@ -46,7 +46,7 @@ namespace Avalonia
         /// <returns>True if the points are equal; otherwise false.</returns>
         public static bool operator ==(PixelPoint left, PixelPoint right)
         {
-            return left.X == right.X && left.Y == right.Y;
+            return left.Equals(right);
         }
 
         /// <summary>
@@ -120,7 +120,7 @@ namespace Avalonia
         /// <returns>The <see cref="PixelPoint"/>.</returns>
         public static PixelPoint Parse(string s)
         {
-            using (var tokenizer = new StringTokenizer(s, CultureInfo.InvariantCulture, exceptionMessage: "Invalid PixelPoint"))
+            using (var tokenizer = new StringTokenizer(s, CultureInfo.InvariantCulture, exceptionMessage: "Invalid PixelPoint."))
             {
                 return new PixelPoint(
                     tokenizer.ReadInt32(),
@@ -128,6 +128,18 @@ namespace Avalonia
             }
         }
 
+        /// <summary>
+        /// Returns a boolean indicating whether the point is equal to the other given point.
+        /// </summary>
+        /// <param name="other">The other point to test equality against.</param>
+        /// <returns>True if this point is equal to other; False otherwise.</returns>
+        public bool Equals(PixelPoint other)
+        {
+            // ReSharper disable CompareOfFloatsByEqualityOperator
+            return X == other.X && Y == other.Y;
+            // ReSharper restore CompareOfFloatsByEqualityOperator
+        }
+
         /// <summary>
         /// Checks for equality between a point and an object.
         /// </summary>
@@ -139,7 +151,7 @@ namespace Avalonia
         {
             if (obj is PixelPoint other)
             {
-                return this == other;
+                return Equals(other);
             }
 
             return false;

+ 14 - 4
src/Avalonia.Visuals/Media/PixelRect.cs

@@ -10,7 +10,7 @@ namespace Avalonia
     /// <summary>
     /// Represents a rectangle in device pixels.
     /// </summary>
-    public readonly struct PixelRect
+    public readonly struct PixelRect : IEquatable<PixelRect>
     {
         /// <summary>
         /// An empty rectangle.
@@ -148,7 +148,7 @@ namespace Avalonia
         /// <returns>True if the rects are equal; otherwise false.</returns>
         public static bool operator ==(PixelRect left, PixelRect right)
         {
-            return left.Position == right.Position && left.Size == right.Size;
+            return left.Equals(right);
         }
 
         /// <summary>
@@ -196,6 +196,16 @@ namespace Avalonia
                 rect.Height);
         }
 
+        /// <summary>
+        /// Returns a boolean indicating whether the rect is equal to the other given rect.
+        /// </summary>
+        /// <param name="other">The other rect to test equality against.</param>
+        /// <returns>True if this rect is equal to other; False otherwise.</returns>
+        public bool Equals(PixelRect other)
+        {
+            return Position == other.Position && Size == other.Size;
+        }
+
         /// <summary>
         /// Returns a boolean indicating whether the given object is equal to this rectangle.
         /// </summary>
@@ -205,7 +215,7 @@ namespace Avalonia
         {
             if (obj is PixelRect other)
             {
-                return this == other;
+                return Equals(other);
             }
 
             return false;
@@ -432,7 +442,7 @@ namespace Avalonia
         /// <returns>The parsed <see cref="PixelRect"/>.</returns>
         public static PixelRect Parse(string s)
         {
-            using (var tokenizer = new StringTokenizer(s, CultureInfo.InvariantCulture, exceptionMessage: "Invalid PixelRect"))
+            using (var tokenizer = new StringTokenizer(s, CultureInfo.InvariantCulture, exceptionMessage: "Invalid PixelRect."))
             {
                 return new PixelRect(
                     tokenizer.ReadInt32(),

+ 14 - 4
src/Avalonia.Visuals/Media/PixelSize.cs

@@ -10,7 +10,7 @@ namespace Avalonia
     /// <summary>
     /// Represents a size in device pixels.
     /// </summary>
-    public readonly struct PixelSize
+    public readonly struct PixelSize : IEquatable<PixelSize>
     {
         /// <summary>
         /// A size representing zero
@@ -51,7 +51,7 @@ namespace Avalonia
         /// <returns>True if the sizes are equal; otherwise false.</returns>
         public static bool operator ==(PixelSize left, PixelSize right)
         {
-            return left.Width == right.Width && left.Height == right.Height;
+            return left.Equals(right);
         }
 
         /// <summary>
@@ -72,7 +72,7 @@ namespace Avalonia
         /// <returns>The <see cref="PixelSize"/>.</returns>
         public static PixelSize Parse(string s)
         {
-            using (var tokenizer = new StringTokenizer(s, CultureInfo.InvariantCulture, exceptionMessage: "Invalid PixelSize"))
+            using (var tokenizer = new StringTokenizer(s, CultureInfo.InvariantCulture, exceptionMessage: "Invalid PixelSize."))
             {
                 return new PixelSize(
                     tokenizer.ReadInt32(),
@@ -80,6 +80,16 @@ namespace Avalonia
             }
         }
 
+        /// <summary>
+        /// Returns a boolean indicating whether the size is equal to the other given size.
+        /// </summary>
+        /// <param name="other">The other size to test equality against.</param>
+        /// <returns>True if this size is equal to other; False otherwise.</returns>
+        public bool Equals(PixelSize other)
+        {
+            return Width == other.Width && Height == other.Height;
+        }
+
         /// <summary>
         /// Checks for equality between a size and an object.
         /// </summary>
@@ -91,7 +101,7 @@ namespace Avalonia
         {
             if (obj is PixelSize other)
             {
-                return this == other;
+                return Equals(other);
             }
 
             return false;

+ 20 - 7
src/Avalonia.Visuals/Point.cs

@@ -1,6 +1,7 @@
 // Copyright (c) The Avalonia Project. All rights reserved.
 // Licensed under the MIT license. See licence.md file in the project root for full license information.
 
+using System;
 using System.Globalization;
 using Avalonia.Animation.Animators;
 using Avalonia.Utilities;
@@ -10,7 +11,7 @@ namespace Avalonia
     /// <summary>
     /// Defines a point.
     /// </summary>
-    public readonly struct Point
+    public readonly struct Point : IEquatable<Point>
     {
         static Point()
         {
@@ -75,7 +76,7 @@ namespace Avalonia
         /// <returns>True if the points are equal; otherwise false.</returns>
         public static bool operator ==(Point left, Point right)
         {
-            return left.X == right.X && left.Y == right.Y;
+            return left.Equals(right);
         }
 
         /// <summary>
@@ -177,7 +178,7 @@ namespace Avalonia
         /// <returns>The <see cref="Thickness"/>.</returns>
         public static Point Parse(string s)
         {
-            using (var tokenizer = new StringTokenizer(s, CultureInfo.InvariantCulture, exceptionMessage: "Invalid Point"))
+            using (var tokenizer = new StringTokenizer(s, CultureInfo.InvariantCulture, exceptionMessage: "Invalid Point."))
             {
                 return new Point(
                     tokenizer.ReadDouble(),
@@ -186,6 +187,19 @@ namespace Avalonia
             }
         }
 
+        /// <summary>
+        /// Returns a boolean indicating whether the point is equal to the other given point.
+        /// </summary>
+        /// <param name="other">The other point to test equality against.</param>
+        /// <returns>True if this point is equal to other; False otherwise.</returns>
+        public bool Equals(Point other)
+        {
+            // ReSharper disable CompareOfFloatsByEqualityOperator
+            return _x == other._x &&
+                   _y == other._y;
+            // ReSharper enable CompareOfFloatsByEqualityOperator
+        }
+
         /// <summary>
         /// Checks for equality between a point and an object.
         /// </summary>
@@ -195,13 +209,12 @@ namespace Avalonia
         /// </returns>
         public override bool Equals(object obj)
         {
-            if (obj is Point)
+            if (!(obj is Point))
             {
-                var other = (Point)obj;
-                return X == other.X && Y == other.Y;
+                return false;
             }
 
-            return false;
+            return Equals((Point)obj);
         }
 
         /// <summary>

+ 27 - 11
src/Avalonia.Visuals/Rect.cs

@@ -11,7 +11,7 @@ namespace Avalonia
     /// <summary>
     /// Defines a rectangle.
     /// </summary>
-    public readonly struct Rect
+    public readonly struct Rect : IEquatable<Rect>
     {
         static Rect()
         {
@@ -164,7 +164,9 @@ namespace Avalonia
         /// <summary>
         /// Gets a value that indicates whether the rectangle is empty.
         /// </summary>
+        // ReSharper disable CompareOfFloatsByEqualityOperator
         public bool IsEmpty => _width == 0 && _height == 0;
+        // ReSharper restore CompareOfFloatsByEqualityOperator
 
         /// <summary>
         /// Checks for equality between two <see cref="Rect"/>s.
@@ -174,7 +176,7 @@ namespace Avalonia
         /// <returns>True if the rects are equal; otherwise false.</returns>
         public static bool operator ==(Rect left, Rect right)
         {
-            return left.Position == right.Position && left.Size == right.Size;
+            return left.Equals(right);
         }
 
         /// <summary>
@@ -297,6 +299,21 @@ namespace Avalonia
                 Size.Deflate(thickness));
         }
 
+        /// <summary>
+        /// Returns a boolean indicating whether the rect is equal to the other given rect.
+        /// </summary>
+        /// <param name="other">The other rect to test equality against.</param>
+        /// <returns>True if this rect is equal to other; False otherwise.</returns>
+        public bool Equals(Rect other)
+        {
+            // ReSharper disable CompareOfFloatsByEqualityOperator
+            return _x == other._x &&
+                   _y == other._y &&
+                   _width == other._width &&
+                   _height == other._height;
+            // ReSharper enable CompareOfFloatsByEqualityOperator
+        }
+
         /// <summary>
         /// Returns a boolean indicating whether the given object is equal to this rectangle.
         /// </summary>
@@ -304,13 +321,12 @@ namespace Avalonia
         /// <returns>True if the object is equal to this rectangle; false otherwise.</returns>
         public override bool Equals(object obj)
         {
-            if (obj is Rect)
+            if (!(obj is Rect))
             {
-                var other = (Rect)obj;
-                return Position == other.Position && Size == other.Size;
+                return false;
             }
 
-            return false;
+            return Equals((Rect)obj);
         }
 
         /// <summary>
@@ -422,10 +438,10 @@ namespace Avalonia
             }
             else
             {
-                var x1 = Math.Min(this.X, rect.X);
-                var x2 = Math.Max(this.Right, rect.Right);
-                var y1 = Math.Min(this.Y, rect.Y);
-                var y2 = Math.Max(this.Bottom, rect.Bottom);
+                var x1 = Math.Min(X, rect.X);
+                var x2 = Math.Max(Right, rect.Right);
+                var y1 = Math.Min(Y, rect.Y);
+                var y2 = Math.Max(Bottom, rect.Bottom);
 
                 return new Rect(new Point(x1, y1), new Point(x2, y2));
             }
@@ -493,7 +509,7 @@ namespace Avalonia
         /// <returns>The parsed <see cref="Rect"/>.</returns>
         public static Rect Parse(string s)
         {
-            using (var tokenizer = new StringTokenizer(s, CultureInfo.InvariantCulture, exceptionMessage: "Invalid Rect"))
+            using (var tokenizer = new StringTokenizer(s, CultureInfo.InvariantCulture, exceptionMessage: "Invalid Rect."))
             {
                 return new Rect(
                     tokenizer.ReadDouble(),

+ 2 - 5
src/Avalonia.Visuals/RelativePoint.cs

@@ -130,10 +130,7 @@ namespace Avalonia
         {
             unchecked
             {
-                int hash = 17;
-                hash = (hash * 23) + Unit.GetHashCode();
-                hash = (hash * 23) + Point.GetHashCode();
-                return hash;
+                return (_point.GetHashCode() * 397) ^ (int)_unit;
             }
         }
 
@@ -156,7 +153,7 @@ namespace Avalonia
         /// <returns>The parsed <see cref="RelativePoint"/>.</returns>
         public static RelativePoint Parse(string s)
         {
-            using (var tokenizer = new StringTokenizer(s, CultureInfo.InvariantCulture, exceptionMessage: "Invalid RelativePoint"))
+            using (var tokenizer = new StringTokenizer(s, CultureInfo.InvariantCulture, exceptionMessage: "Invalid RelativePoint."))
             {
                 var x = tokenizer.ReadString();
                 var y = tokenizer.ReadString();

+ 3 - 6
src/Avalonia.Visuals/RelativeRect.cs

@@ -139,10 +139,7 @@ namespace Avalonia
         {
             unchecked
             {
-                int hash = 17;
-                hash = (hash * 23) + Unit.GetHashCode();
-                hash = (hash * 23) + Rect.GetHashCode();
-                return hash;
+                return ((int)Unit * 397) ^ Rect.GetHashCode();
             }
         }
 
@@ -161,7 +158,7 @@ namespace Avalonia
                     Rect.Width * size.Width,
                     Rect.Height * size.Height);
         }
-        
+
         /// <summary>
         /// Parses a <see cref="RelativeRect"/> string.
         /// </summary>
@@ -169,7 +166,7 @@ namespace Avalonia
         /// <returns>The parsed <see cref="RelativeRect"/>.</returns>
         public static RelativeRect Parse(string s)
         {
-            using (var tokenizer = new StringTokenizer(s, exceptionMessage: "Invalid RelativeRect"))
+            using (var tokenizer = new StringTokenizer(s, exceptionMessage: "Invalid RelativeRect."))
             {
                 var x = tokenizer.ReadString();
                 var y = tokenizer.ReadString();

+ 19 - 7
src/Avalonia.Visuals/Size.cs

@@ -11,7 +11,7 @@ namespace Avalonia
     /// <summary>
     /// Defines a size.
     /// </summary>
-    public readonly struct Size
+    public readonly struct Size : IEquatable<Size>
     {
         static Size()
         {
@@ -72,7 +72,7 @@ namespace Avalonia
         /// <returns>True if the sizes are equal; otherwise false.</returns>
         public static bool operator ==(Size left, Size right)
         {
-            return left._width == right._width && left._height == right._height;
+            return left.Equals(right);
         }
 
         /// <summary>
@@ -158,7 +158,7 @@ namespace Avalonia
         /// <returns>The <see cref="Size"/>.</returns>
         public static Size Parse(string s)
         {
-            using (var tokenizer = new StringTokenizer(s, CultureInfo.InvariantCulture, exceptionMessage: "Invalid Size"))
+            using (var tokenizer = new StringTokenizer(s, CultureInfo.InvariantCulture, exceptionMessage: "Invalid Size."))
             {
                 return new Size(
                     tokenizer.ReadDouble(),
@@ -191,6 +191,19 @@ namespace Avalonia
                 Math.Max(0, _height - thickness.Top - thickness.Bottom));
         }
 
+        /// <summary>
+        /// Returns a boolean indicating whether the size is equal to the other given size.
+        /// </summary>
+        /// <param name="other">The other size to test equality against.</param>
+        /// <returns>True if this size is equal to other; False otherwise.</returns>
+        public bool Equals(Size other)
+        {
+            // ReSharper disable CompareOfFloatsByEqualityOperator
+            return _width == other._width &&
+                   _height == other._height;
+            // ReSharper enable CompareOfFloatsByEqualityOperator
+        }
+
         /// <summary>
         /// Checks for equality between a size and an object.
         /// </summary>
@@ -200,13 +213,12 @@ namespace Avalonia
         /// </returns>
         public override bool Equals(object obj)
         {
-            if (obj is Size)
+            if (!(obj is Size))
             {
-                var other = (Size)obj;
-                return Width == other.Width && Height == other.Height;
+                return false;
             }
 
-            return false;
+            return Equals((Size)obj);
         }
 
         /// <summary>

+ 23 - 11
src/Avalonia.Visuals/Thickness.cs

@@ -3,7 +3,6 @@
 
 using System;
 using System.Globalization;
-using Avalonia.Animation;
 using Avalonia.Animation.Animators;
 using Avalonia.Utilities;
 
@@ -12,7 +11,7 @@ namespace Avalonia
     /// <summary>
     /// Describes the thickness of a frame around a rectangle.
     /// </summary>
-    public readonly struct Thickness
+    public readonly struct Thickness : IEquatable<Thickness>
     {
         static Thickness()
         {
@@ -204,7 +203,9 @@ namespace Avalonia
         /// <returns>The <see cref="Thickness"/>.</returns>
         public static Thickness Parse(string s)
         {
-            using (var tokenizer = new StringTokenizer(s, CultureInfo.InvariantCulture, exceptionMessage: "Invalid Thickness"))
+            const string exceptionMessage = "Invalid Thickness.";
+
+            using (var tokenizer = new StringTokenizer(s, CultureInfo.InvariantCulture, exceptionMessage))
             {
                 if (tokenizer.TryReadDouble(out var a))
                 {
@@ -221,10 +222,25 @@ namespace Avalonia
                     return new Thickness(a);
                 }
 
-                throw new FormatException("Invalid Thickness.");
+                throw new FormatException(exceptionMessage);
             }
         }
 
+        /// <summary>
+        /// Returns a boolean indicating whether the thickness is equal to the other given point.
+        /// </summary>
+        /// <param name="other">The other thickness to test equality against.</param>
+        /// <returns>True if this thickness is equal to other; False otherwise.</returns>
+        public bool Equals(Thickness other)
+        {
+            // ReSharper disable CompareOfFloatsByEqualityOperator
+            return _left == other._left &&
+                   _top == other._top &&
+                   _right == other._right &&
+                   _bottom == other._bottom;
+            // ReSharper restore CompareOfFloatsByEqualityOperator
+        }
+
         /// <summary>
         /// Checks for equality between a thickness and an object.
         /// </summary>
@@ -234,16 +250,12 @@ namespace Avalonia
         /// </returns>
         public override bool Equals(object obj)
         {
-            if (obj is Thickness)
+            if (!(obj is Thickness))
             {
-                Thickness other = (Thickness)obj;
-                return Left == other.Left &&
-                       Top == other.Top &&
-                       Right == other.Right &&
-                       Bottom == other.Bottom;
+                return false;
             }
 
-            return false;
+            return Equals((Thickness)obj);
         }
 
         /// <summary>

+ 1 - 1
src/Avalonia.Visuals/Vector.cs

@@ -11,7 +11,7 @@ namespace Avalonia
     /// <summary>
     /// Defines a vector.
     /// </summary>
-    public readonly struct Vector
+    public readonly struct Vector : IEquatable<Vector>
     {
         static Vector()
         {

+ 2 - 1
src/Avalonia.Visuals/VisualTree/TransformedBounds.cs

@@ -1,13 +1,14 @@
 // Copyright (c) The Avalonia Project. All rights reserved.
 // Licensed under the MIT license. See licence.md file in the project root for full license information.
 
+using System;
 
 namespace Avalonia.VisualTree
 {
     /// <summary>
     /// Holds information about the bounds of a control, together with a transform and a clip.
     /// </summary>
-    public readonly struct TransformedBounds
+    public readonly struct TransformedBounds : IEquatable<TransformedBounds>
     {
         /// <summary>
         /// Initializes a new instance of the <see cref="TransformedBounds"/> struct.