﻿//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated by \generate-code.bat.
//
//     Changes to this file will be lost when the code is regenerated.
//     The build server regenerates the code before each build and a pre-build
//     step will regenerate the code on each local build.
//
//     See https://github.com/angularsen/UnitsNet/wiki/Adding-a-New-Unit for how to add or edit units.
//
//     Add CustomCode\Quantities\MyQuantity.extra.cs files to add code to generated quantities.
//     Add UnitDefinitions\MyQuantity.json and run generate-code.bat to generate new units or quantities.
//
// </auto-generated>
//------------------------------------------------------------------------------

// Licensed under MIT No Attribution, see LICENSE file at the root.
// Copyright 2013 Andreas Gullberg Larsen (andreas.larsen84@gmail.com). Maintained at https://github.com/angularsen/UnitsNet.

using System;
using System.Globalization;
using System.Linq;
using JetBrains.Annotations;
using UnitsNet.InternalHelpers;
using UnitsNet.Units;

#nullable enable

// ReSharper disable once CheckNamespace

namespace UnitsNet
{
    /// <inheritdoc />
    /// <summary>
    ///     Many different units of length have been used around the world. The main units in modern use are U.S. customary units in the United States and the Metric system elsewhere. British Imperial units are still used for some purposes in the United Kingdom and some other countries. The metric system is sub-divided into SI and non-SI units.
    /// </summary>
    public partial struct Length : IQuantity<LengthUnit>, IEquatable<Length>, IComparable, IComparable<Length>, IConvertible, IFormattable
    {
        /// <summary>
        ///     The numeric value this quantity was constructed with.
        /// </summary>
        private readonly double _value;

        /// <summary>
        ///     The unit this quantity was constructed with.
        /// </summary>
        private readonly LengthUnit? _unit;

        static Length()
        {
            BaseDimensions = new BaseDimensions(1, 0, 0, 0, 0, 0, 0);

            Info = new QuantityInfo<LengthUnit>("Length",
                new UnitInfo<LengthUnit>[] {
                    new UnitInfo<LengthUnit>(LengthUnit.AstronomicalUnit, BaseUnits.Undefined),
                    new UnitInfo<LengthUnit>(LengthUnit.Centimeter, BaseUnits.Undefined),
                    new UnitInfo<LengthUnit>(LengthUnit.Chain, new BaseUnits(length: LengthUnit.Chain)),
                    new UnitInfo<LengthUnit>(LengthUnit.Decimeter, BaseUnits.Undefined),
                    new UnitInfo<LengthUnit>(LengthUnit.DtpPica, new BaseUnits(length: LengthUnit.DtpPica)),
                    new UnitInfo<LengthUnit>(LengthUnit.DtpPoint, new BaseUnits(length: LengthUnit.DtpPoint)),
                    new UnitInfo<LengthUnit>(LengthUnit.Fathom, new BaseUnits(length: LengthUnit.Fathom)),
                    new UnitInfo<LengthUnit>(LengthUnit.Foot, new BaseUnits(length: LengthUnit.Foot)),
                    new UnitInfo<LengthUnit>(LengthUnit.Hand, new BaseUnits(length: LengthUnit.Hand)),
                    new UnitInfo<LengthUnit>(LengthUnit.Hectometer, BaseUnits.Undefined),
                    new UnitInfo<LengthUnit>(LengthUnit.Inch, new BaseUnits(length: LengthUnit.Inch)),
                    new UnitInfo<LengthUnit>(LengthUnit.KilolightYear, BaseUnits.Undefined),
                    new UnitInfo<LengthUnit>(LengthUnit.Kilometer, BaseUnits.Undefined),
                    new UnitInfo<LengthUnit>(LengthUnit.Kiloparsec, BaseUnits.Undefined),
                    new UnitInfo<LengthUnit>(LengthUnit.LightYear, BaseUnits.Undefined),
                    new UnitInfo<LengthUnit>(LengthUnit.MegalightYear, BaseUnits.Undefined),
                    new UnitInfo<LengthUnit>(LengthUnit.Megaparsec, BaseUnits.Undefined),
                    new UnitInfo<LengthUnit>(LengthUnit.Meter, new BaseUnits(length: LengthUnit.Meter)),
                    new UnitInfo<LengthUnit>(LengthUnit.Microinch, new BaseUnits(length: LengthUnit.Microinch)),
                    new UnitInfo<LengthUnit>(LengthUnit.Micrometer, BaseUnits.Undefined),
                    new UnitInfo<LengthUnit>(LengthUnit.Mil, new BaseUnits(length: LengthUnit.Mil)),
                    new UnitInfo<LengthUnit>(LengthUnit.Mile, new BaseUnits(length: LengthUnit.Mile)),
                    new UnitInfo<LengthUnit>(LengthUnit.Millimeter, BaseUnits.Undefined),
                    new UnitInfo<LengthUnit>(LengthUnit.Nanometer, BaseUnits.Undefined),
                    new UnitInfo<LengthUnit>(LengthUnit.NauticalMile, new BaseUnits(length: LengthUnit.NauticalMile)),
                    new UnitInfo<LengthUnit>(LengthUnit.Parsec, BaseUnits.Undefined),
                    new UnitInfo<LengthUnit>(LengthUnit.PrinterPica, new BaseUnits(length: LengthUnit.PrinterPica)),
                    new UnitInfo<LengthUnit>(LengthUnit.PrinterPoint, new BaseUnits(length: LengthUnit.PrinterPoint)),
                    new UnitInfo<LengthUnit>(LengthUnit.Shackle, new BaseUnits(length: LengthUnit.Shackle)),
                    new UnitInfo<LengthUnit>(LengthUnit.SolarRadius, BaseUnits.Undefined),
                    new UnitInfo<LengthUnit>(LengthUnit.Twip, new BaseUnits(length: LengthUnit.Twip)),
                    new UnitInfo<LengthUnit>(LengthUnit.UsSurveyFoot, new BaseUnits(length: LengthUnit.UsSurveyFoot)),
                    new UnitInfo<LengthUnit>(LengthUnit.Yard, new BaseUnits(length: LengthUnit.Yard)),
                },
                BaseUnit, Zero, BaseDimensions, QuantityType.Length);
        }

        /// <summary>
        ///     Creates the quantity with the given numeric value and unit.
        /// </summary>
        /// <param name="value">The numeric value to construct this quantity with.</param>
        /// <param name="unit">The unit representation to construct this quantity with.</param>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public Length(double value, LengthUnit unit)
        {
            if(unit == LengthUnit.Undefined)
              throw new ArgumentException("The quantity can not be created with an undefined unit.", nameof(unit));

            _value = Guard.EnsureValidNumber(value, nameof(value));
            _unit = unit;
        }

        /// <summary>
        /// Creates an instance of the quantity with the given numeric value in units compatible with the given <see cref="UnitSystem"/>.
        /// If multiple compatible units were found, the first match is used.
        /// </summary>
        /// <param name="value">The numeric value to construct this quantity with.</param>
        /// <param name="unitSystem">The unit system to create the quantity with.</param>
        /// <exception cref="ArgumentNullException">The given <see cref="UnitSystem"/> is null.</exception>
        /// <exception cref="ArgumentException">No unit was found for the given <see cref="UnitSystem"/>.</exception>
        public Length(double value, UnitSystem unitSystem)
        {
            if(unitSystem is null) throw new ArgumentNullException(nameof(unitSystem));

            var unitInfos = Info.GetUnitInfosFor(unitSystem.BaseUnits);
            var firstUnitInfo = unitInfos.FirstOrDefault();

            _value = Guard.EnsureValidNumber(value, nameof(value));
            _unit = firstUnitInfo?.Value ?? throw new ArgumentException("No units were found for the given UnitSystem.", nameof(unitSystem));
        }

        #region Static Properties

        /// <inheritdoc cref="IQuantity.QuantityInfo"/>
        public static QuantityInfo<LengthUnit> Info { get; }

        /// <summary>
        ///     The <see cref="BaseDimensions" /> of this quantity.
        /// </summary>
        public static BaseDimensions BaseDimensions { get; }

        /// <summary>
        ///     The base unit of Length, which is Meter. All conversions go via this value.
        /// </summary>
        public static LengthUnit BaseUnit { get; } = LengthUnit.Meter;

        /// <summary>
        /// Represents the largest possible value of Length
        /// </summary>
        public static Length MaxValue { get; } = new Length(double.MaxValue, BaseUnit);

        /// <summary>
        /// Represents the smallest possible value of Length
        /// </summary>
        public static Length MinValue { get; } = new Length(double.MinValue, BaseUnit);

        /// <summary>
        ///     The <see cref="QuantityType" /> of this quantity.
        /// </summary>
        [Obsolete("QuantityType will be removed in the future. Use Info property instead.")]
        public static QuantityType QuantityType { get; } = QuantityType.Length;

        /// <summary>
        ///     All units of measurement for the Length quantity.
        /// </summary>
        public static LengthUnit[] Units { get; } = Enum.GetValues(typeof(LengthUnit)).Cast<LengthUnit>().Except(new LengthUnit[]{ LengthUnit.Undefined }).ToArray();

        /// <summary>
        ///     Gets an instance of this quantity with a value of 0 in the base unit Meter.
        /// </summary>
        public static Length Zero { get; } = new Length(0, BaseUnit);

        #endregion

        #region Properties

        /// <summary>
        ///     The numeric value this quantity was constructed with.
        /// </summary>
        public double Value => _value;

        Enum IQuantity.Unit => Unit;

        /// <inheritdoc />
        public LengthUnit Unit => _unit.GetValueOrDefault(BaseUnit);

        /// <inheritdoc />
        public QuantityInfo<LengthUnit> QuantityInfo => Info;

        /// <inheritdoc cref="IQuantity.QuantityInfo"/>
        QuantityInfo IQuantity.QuantityInfo => Info;

        /// <summary>
        ///     The <see cref="QuantityType" /> of this quantity.
        /// </summary>
        public QuantityType Type => Length.QuantityType;

        /// <summary>
        ///     The <see cref="BaseDimensions" /> of this quantity.
        /// </summary>
        public BaseDimensions Dimensions => Length.BaseDimensions;

        #endregion

        #region Conversion Properties

        /// <summary>
        ///     Get Length in AstronomicalUnits.
        /// </summary>
        public double AstronomicalUnits => As(LengthUnit.AstronomicalUnit);

        /// <summary>
        ///     Get Length in Centimeters.
        /// </summary>
        public double Centimeters => As(LengthUnit.Centimeter);

        /// <summary>
        ///     Get Length in Chains.
        /// </summary>
        public double Chains => As(LengthUnit.Chain);

        /// <summary>
        ///     Get Length in Decimeters.
        /// </summary>
        public double Decimeters => As(LengthUnit.Decimeter);

        /// <summary>
        ///     Get Length in DtpPicas.
        /// </summary>
        public double DtpPicas => As(LengthUnit.DtpPica);

        /// <summary>
        ///     Get Length in DtpPoints.
        /// </summary>
        public double DtpPoints => As(LengthUnit.DtpPoint);

        /// <summary>
        ///     Get Length in Fathoms.
        /// </summary>
        public double Fathoms => As(LengthUnit.Fathom);

        /// <summary>
        ///     Get Length in Feet.
        /// </summary>
        public double Feet => As(LengthUnit.Foot);

        /// <summary>
        ///     Get Length in Hands.
        /// </summary>
        public double Hands => As(LengthUnit.Hand);

        /// <summary>
        ///     Get Length in Hectometers.
        /// </summary>
        public double Hectometers => As(LengthUnit.Hectometer);

        /// <summary>
        ///     Get Length in Inches.
        /// </summary>
        public double Inches => As(LengthUnit.Inch);

        /// <summary>
        ///     Get Length in KilolightYears.
        /// </summary>
        public double KilolightYears => As(LengthUnit.KilolightYear);

        /// <summary>
        ///     Get Length in Kilometers.
        /// </summary>
        public double Kilometers => As(LengthUnit.Kilometer);

        /// <summary>
        ///     Get Length in Kiloparsecs.
        /// </summary>
        public double Kiloparsecs => As(LengthUnit.Kiloparsec);

        /// <summary>
        ///     Get Length in LightYears.
        /// </summary>
        public double LightYears => As(LengthUnit.LightYear);

        /// <summary>
        ///     Get Length in MegalightYears.
        /// </summary>
        public double MegalightYears => As(LengthUnit.MegalightYear);

        /// <summary>
        ///     Get Length in Megaparsecs.
        /// </summary>
        public double Megaparsecs => As(LengthUnit.Megaparsec);

        /// <summary>
        ///     Get Length in Meters.
        /// </summary>
        public double Meters => As(LengthUnit.Meter);

        /// <summary>
        ///     Get Length in Microinches.
        /// </summary>
        public double Microinches => As(LengthUnit.Microinch);

        /// <summary>
        ///     Get Length in Micrometers.
        /// </summary>
        public double Micrometers => As(LengthUnit.Micrometer);

        /// <summary>
        ///     Get Length in Mils.
        /// </summary>
        public double Mils => As(LengthUnit.Mil);

        /// <summary>
        ///     Get Length in Miles.
        /// </summary>
        public double Miles => As(LengthUnit.Mile);

        /// <summary>
        ///     Get Length in Millimeters.
        /// </summary>
        public double Millimeters => As(LengthUnit.Millimeter);

        /// <summary>
        ///     Get Length in Nanometers.
        /// </summary>
        public double Nanometers => As(LengthUnit.Nanometer);

        /// <summary>
        ///     Get Length in NauticalMiles.
        /// </summary>
        public double NauticalMiles => As(LengthUnit.NauticalMile);

        /// <summary>
        ///     Get Length in Parsecs.
        /// </summary>
        public double Parsecs => As(LengthUnit.Parsec);

        /// <summary>
        ///     Get Length in PrinterPicas.
        /// </summary>
        public double PrinterPicas => As(LengthUnit.PrinterPica);

        /// <summary>
        ///     Get Length in PrinterPoints.
        /// </summary>
        public double PrinterPoints => As(LengthUnit.PrinterPoint);

        /// <summary>
        ///     Get Length in Shackles.
        /// </summary>
        public double Shackles => As(LengthUnit.Shackle);

        /// <summary>
        ///     Get Length in SolarRadiuses.
        /// </summary>
        public double SolarRadiuses => As(LengthUnit.SolarRadius);

        /// <summary>
        ///     Get Length in Twips.
        /// </summary>
        public double Twips => As(LengthUnit.Twip);

        /// <summary>
        ///     Get Length in UsSurveyFeet.
        /// </summary>
        public double UsSurveyFeet => As(LengthUnit.UsSurveyFoot);

        /// <summary>
        ///     Get Length in Yards.
        /// </summary>
        public double Yards => As(LengthUnit.Yard);

        #endregion

        #region Static Methods

        /// <summary>
        ///     Get unit abbreviation string.
        /// </summary>
        /// <param name="unit">Unit to get abbreviation for.</param>
        /// <returns>Unit abbreviation string.</returns>
        public static string GetAbbreviation(LengthUnit unit)
        {
            return GetAbbreviation(unit, null);
        }

        /// <summary>
        ///     Get unit abbreviation string.
        /// </summary>
        /// <param name="unit">Unit to get abbreviation for.</param>
        /// <returns>Unit abbreviation string.</returns>
        /// <param name="provider">Format to use for localization. Defaults to <see cref="CultureInfo.CurrentUICulture" /> if null.</param>
        public static string GetAbbreviation(LengthUnit unit, IFormatProvider? provider)
        {
            return UnitAbbreviationsCache.Default.GetDefaultAbbreviation(unit, provider);
        }

        #endregion

        #region Static Factory Methods

        /// <summary>
        ///     Get Length from AstronomicalUnits.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromAstronomicalUnits(QuantityValue astronomicalunits)
        {
            double value = (double) astronomicalunits;
            return new Length(value, LengthUnit.AstronomicalUnit);
        }
        /// <summary>
        ///     Get Length from Centimeters.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromCentimeters(QuantityValue centimeters)
        {
            double value = (double) centimeters;
            return new Length(value, LengthUnit.Centimeter);
        }
        /// <summary>
        ///     Get Length from Chains.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromChains(QuantityValue chains)
        {
            double value = (double) chains;
            return new Length(value, LengthUnit.Chain);
        }
        /// <summary>
        ///     Get Length from Decimeters.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromDecimeters(QuantityValue decimeters)
        {
            double value = (double) decimeters;
            return new Length(value, LengthUnit.Decimeter);
        }
        /// <summary>
        ///     Get Length from DtpPicas.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromDtpPicas(QuantityValue dtppicas)
        {
            double value = (double) dtppicas;
            return new Length(value, LengthUnit.DtpPica);
        }
        /// <summary>
        ///     Get Length from DtpPoints.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromDtpPoints(QuantityValue dtppoints)
        {
            double value = (double) dtppoints;
            return new Length(value, LengthUnit.DtpPoint);
        }
        /// <summary>
        ///     Get Length from Fathoms.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromFathoms(QuantityValue fathoms)
        {
            double value = (double) fathoms;
            return new Length(value, LengthUnit.Fathom);
        }
        /// <summary>
        ///     Get Length from Feet.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromFeet(QuantityValue feet)
        {
            double value = (double) feet;
            return new Length(value, LengthUnit.Foot);
        }
        /// <summary>
        ///     Get Length from Hands.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromHands(QuantityValue hands)
        {
            double value = (double) hands;
            return new Length(value, LengthUnit.Hand);
        }
        /// <summary>
        ///     Get Length from Hectometers.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromHectometers(QuantityValue hectometers)
        {
            double value = (double) hectometers;
            return new Length(value, LengthUnit.Hectometer);
        }
        /// <summary>
        ///     Get Length from Inches.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromInches(QuantityValue inches)
        {
            double value = (double) inches;
            return new Length(value, LengthUnit.Inch);
        }
        /// <summary>
        ///     Get Length from KilolightYears.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromKilolightYears(QuantityValue kilolightyears)
        {
            double value = (double) kilolightyears;
            return new Length(value, LengthUnit.KilolightYear);
        }
        /// <summary>
        ///     Get Length from Kilometers.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromKilometers(QuantityValue kilometers)
        {
            double value = (double) kilometers;
            return new Length(value, LengthUnit.Kilometer);
        }
        /// <summary>
        ///     Get Length from Kiloparsecs.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromKiloparsecs(QuantityValue kiloparsecs)
        {
            double value = (double) kiloparsecs;
            return new Length(value, LengthUnit.Kiloparsec);
        }
        /// <summary>
        ///     Get Length from LightYears.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromLightYears(QuantityValue lightyears)
        {
            double value = (double) lightyears;
            return new Length(value, LengthUnit.LightYear);
        }
        /// <summary>
        ///     Get Length from MegalightYears.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromMegalightYears(QuantityValue megalightyears)
        {
            double value = (double) megalightyears;
            return new Length(value, LengthUnit.MegalightYear);
        }
        /// <summary>
        ///     Get Length from Megaparsecs.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromMegaparsecs(QuantityValue megaparsecs)
        {
            double value = (double) megaparsecs;
            return new Length(value, LengthUnit.Megaparsec);
        }
        /// <summary>
        ///     Get Length from Meters.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromMeters(QuantityValue meters)
        {
            double value = (double) meters;
            return new Length(value, LengthUnit.Meter);
        }
        /// <summary>
        ///     Get Length from Microinches.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromMicroinches(QuantityValue microinches)
        {
            double value = (double) microinches;
            return new Length(value, LengthUnit.Microinch);
        }
        /// <summary>
        ///     Get Length from Micrometers.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromMicrometers(QuantityValue micrometers)
        {
            double value = (double) micrometers;
            return new Length(value, LengthUnit.Micrometer);
        }
        /// <summary>
        ///     Get Length from Mils.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromMils(QuantityValue mils)
        {
            double value = (double) mils;
            return new Length(value, LengthUnit.Mil);
        }
        /// <summary>
        ///     Get Length from Miles.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromMiles(QuantityValue miles)
        {
            double value = (double) miles;
            return new Length(value, LengthUnit.Mile);
        }
        /// <summary>
        ///     Get Length from Millimeters.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromMillimeters(QuantityValue millimeters)
        {
            double value = (double) millimeters;
            return new Length(value, LengthUnit.Millimeter);
        }
        /// <summary>
        ///     Get Length from Nanometers.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromNanometers(QuantityValue nanometers)
        {
            double value = (double) nanometers;
            return new Length(value, LengthUnit.Nanometer);
        }
        /// <summary>
        ///     Get Length from NauticalMiles.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromNauticalMiles(QuantityValue nauticalmiles)
        {
            double value = (double) nauticalmiles;
            return new Length(value, LengthUnit.NauticalMile);
        }
        /// <summary>
        ///     Get Length from Parsecs.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromParsecs(QuantityValue parsecs)
        {
            double value = (double) parsecs;
            return new Length(value, LengthUnit.Parsec);
        }
        /// <summary>
        ///     Get Length from PrinterPicas.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromPrinterPicas(QuantityValue printerpicas)
        {
            double value = (double) printerpicas;
            return new Length(value, LengthUnit.PrinterPica);
        }
        /// <summary>
        ///     Get Length from PrinterPoints.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromPrinterPoints(QuantityValue printerpoints)
        {
            double value = (double) printerpoints;
            return new Length(value, LengthUnit.PrinterPoint);
        }
        /// <summary>
        ///     Get Length from Shackles.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromShackles(QuantityValue shackles)
        {
            double value = (double) shackles;
            return new Length(value, LengthUnit.Shackle);
        }
        /// <summary>
        ///     Get Length from SolarRadiuses.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromSolarRadiuses(QuantityValue solarradiuses)
        {
            double value = (double) solarradiuses;
            return new Length(value, LengthUnit.SolarRadius);
        }
        /// <summary>
        ///     Get Length from Twips.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromTwips(QuantityValue twips)
        {
            double value = (double) twips;
            return new Length(value, LengthUnit.Twip);
        }
        /// <summary>
        ///     Get Length from UsSurveyFeet.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromUsSurveyFeet(QuantityValue ussurveyfeet)
        {
            double value = (double) ussurveyfeet;
            return new Length(value, LengthUnit.UsSurveyFoot);
        }
        /// <summary>
        ///     Get Length from Yards.
        /// </summary>
        /// <exception cref="ArgumentException">If value is NaN or Infinity.</exception>
        public static Length FromYards(QuantityValue yards)
        {
            double value = (double) yards;
            return new Length(value, LengthUnit.Yard);
        }

        /// <summary>
        ///     Dynamically convert from value and unit enum <see cref="LengthUnit" /> to <see cref="Length" />.
        /// </summary>
        /// <param name="value">Value to convert from.</param>
        /// <param name="fromUnit">Unit to convert from.</param>
        /// <returns>Length unit value.</returns>
        public static Length From(QuantityValue value, LengthUnit fromUnit)
        {
            return new Length((double)value, fromUnit);
        }

        #endregion

        #region Static Parse Methods

        /// <summary>
        ///     Parse a string with one or two quantities of the format "&lt;quantity&gt; &lt;unit&gt;".
        /// </summary>
        /// <param name="str">String to parse. Typically in the form: {number} {unit}</param>
        /// <example>
        ///     Length.Parse("5.5 m", new CultureInfo("en-US"));
        /// </example>
        /// <exception cref="ArgumentNullException">The value of 'str' cannot be null. </exception>
        /// <exception cref="ArgumentException">
        ///     Expected string to have one or two pairs of quantity and unit in the format
        ///     "&lt;quantity&gt; &lt;unit&gt;". Eg. "5.5 m" or "1ft 2in"
        /// </exception>
        /// <exception cref="AmbiguousUnitParseException">
        ///     More than one unit is represented by the specified unit abbreviation.
        ///     Example: Volume.Parse("1 cup") will throw, because it can refer to any of
        ///     <see cref="VolumeUnit.MetricCup" />, <see cref="VolumeUnit.UsLegalCup" /> and <see cref="VolumeUnit.UsCustomaryCup" />.
        /// </exception>
        /// <exception cref="UnitsNetException">
        ///     If anything else goes wrong, typically due to a bug or unhandled case.
        ///     We wrap exceptions in <see cref="UnitsNetException" /> to allow you to distinguish
        ///     Units.NET exceptions from other exceptions.
        /// </exception>
        public static Length Parse(string str)
        {
            return Parse(str, null);
        }

        /// <summary>
        ///     Parse a string with one or two quantities of the format "&lt;quantity&gt; &lt;unit&gt;".
        /// </summary>
        /// <param name="str">String to parse. Typically in the form: {number} {unit}</param>
        /// <example>
        ///     Length.Parse("5.5 m", new CultureInfo("en-US"));
        /// </example>
        /// <exception cref="ArgumentNullException">The value of 'str' cannot be null. </exception>
        /// <exception cref="ArgumentException">
        ///     Expected string to have one or two pairs of quantity and unit in the format
        ///     "&lt;quantity&gt; &lt;unit&gt;". Eg. "5.5 m" or "1ft 2in"
        /// </exception>
        /// <exception cref="AmbiguousUnitParseException">
        ///     More than one unit is represented by the specified unit abbreviation.
        ///     Example: Volume.Parse("1 cup") will throw, because it can refer to any of
        ///     <see cref="VolumeUnit.MetricCup" />, <see cref="VolumeUnit.UsLegalCup" /> and <see cref="VolumeUnit.UsCustomaryCup" />.
        /// </exception>
        /// <exception cref="UnitsNetException">
        ///     If anything else goes wrong, typically due to a bug or unhandled case.
        ///     We wrap exceptions in <see cref="UnitsNetException" /> to allow you to distinguish
        ///     Units.NET exceptions from other exceptions.
        /// </exception>
        /// <param name="provider">Format to use when parsing number and unit. Defaults to <see cref="CultureInfo.CurrentUICulture" /> if null.</param>
        public static Length Parse(string str, IFormatProvider? provider)
        {
            return QuantityParser.Default.Parse<Length, LengthUnit>(
                str,
                provider,
                From);
        }

        /// <summary>
        ///     Try to parse a string with one or two quantities of the format "&lt;quantity&gt; &lt;unit&gt;".
        /// </summary>
        /// <param name="str">String to parse. Typically in the form: {number} {unit}</param>
        /// <param name="result">Resulting unit quantity if successful.</param>
        /// <example>
        ///     Length.Parse("5.5 m", new CultureInfo("en-US"));
        /// </example>
        public static bool TryParse(string? str, out Length result)
        {
            return TryParse(str, null, out result);
        }

        /// <summary>
        ///     Try to parse a string with one or two quantities of the format "&lt;quantity&gt; &lt;unit&gt;".
        /// </summary>
        /// <param name="str">String to parse. Typically in the form: {number} {unit}</param>
        /// <param name="result">Resulting unit quantity if successful.</param>
        /// <returns>True if successful, otherwise false.</returns>
        /// <example>
        ///     Length.Parse("5.5 m", new CultureInfo("en-US"));
        /// </example>
        /// <param name="provider">Format to use when parsing number and unit. Defaults to <see cref="CultureInfo.CurrentUICulture" /> if null.</param>
        public static bool TryParse(string? str, IFormatProvider? provider, out Length result)
        {
            return QuantityParser.Default.TryParse<Length, LengthUnit>(
                str,
                provider,
                From,
                out result);
        }

        /// <summary>
        ///     Parse a unit string.
        /// </summary>
        /// <param name="str">String to parse. Typically in the form: {number} {unit}</param>
        /// <example>
        ///     Length.ParseUnit("m", new CultureInfo("en-US"));
        /// </example>
        /// <exception cref="ArgumentNullException">The value of 'str' cannot be null. </exception>
        /// <exception cref="UnitsNetException">Error parsing string.</exception>
        public static LengthUnit ParseUnit(string str)
        {
            return ParseUnit(str, null);
        }

        /// <summary>
        ///     Parse a unit string.
        /// </summary>
        /// <param name="str">String to parse. Typically in the form: {number} {unit}</param>
        /// <param name="provider">Format to use when parsing number and unit. Defaults to <see cref="CultureInfo.CurrentUICulture" /> if null.</param>
        /// <example>
        ///     Length.ParseUnit("m", new CultureInfo("en-US"));
        /// </example>
        /// <exception cref="ArgumentNullException">The value of 'str' cannot be null. </exception>
        /// <exception cref="UnitsNetException">Error parsing string.</exception>
        public static LengthUnit ParseUnit(string str, IFormatProvider? provider)
        {
            return UnitParser.Default.Parse<LengthUnit>(str, provider);
        }

        /// <inheritdoc cref="TryParseUnit(string,IFormatProvider,out UnitsNet.Units.LengthUnit)"/>
        public static bool TryParseUnit(string str, out LengthUnit unit)
        {
            return TryParseUnit(str, null, out unit);
        }

        /// <summary>
        ///     Parse a unit string.
        /// </summary>
        /// <param name="str">String to parse. Typically in the form: {number} {unit}</param>
        /// <param name="unit">The parsed unit if successful.</param>
        /// <returns>True if successful, otherwise false.</returns>
        /// <example>
        ///     Length.TryParseUnit("m", new CultureInfo("en-US"));
        /// </example>
        /// <param name="provider">Format to use when parsing number and unit. Defaults to <see cref="CultureInfo.CurrentUICulture" /> if null.</param>
        public static bool TryParseUnit(string str, IFormatProvider? provider, out LengthUnit unit)
        {
            return UnitParser.Default.TryParse<LengthUnit>(str, provider, out unit);
        }

        #endregion

        #region Arithmetic Operators

        /// <summary>Negate the value.</summary>
        public static Length operator -(Length right)
        {
            return new Length(-right.Value, right.Unit);
        }

        /// <summary>Get <see cref="Length"/> from adding two <see cref="Length"/>.</summary>
        public static Length operator +(Length left, Length right)
        {
            return new Length(left.Value + right.GetValueAs(left.Unit), left.Unit);
        }

        /// <summary>Get <see cref="Length"/> from subtracting two <see cref="Length"/>.</summary>
        public static Length operator -(Length left, Length right)
        {
            return new Length(left.Value - right.GetValueAs(left.Unit), left.Unit);
        }

        /// <summary>Get <see cref="Length"/> from multiplying value and <see cref="Length"/>.</summary>
        public static Length operator *(double left, Length right)
        {
            return new Length(left * right.Value, right.Unit);
        }

        /// <summary>Get <see cref="Length"/> from multiplying value and <see cref="Length"/>.</summary>
        public static Length operator *(Length left, double right)
        {
            return new Length(left.Value * right, left.Unit);
        }

        /// <summary>Get <see cref="Length"/> from dividing <see cref="Length"/> by value.</summary>
        public static Length operator /(Length left, double right)
        {
            return new Length(left.Value / right, left.Unit);
        }

        /// <summary>Get ratio value from dividing <see cref="Length"/> by <see cref="Length"/>.</summary>
        public static double operator /(Length left, Length right)
        {
            return left.Meters / right.Meters;
        }

        #endregion

        #region Equality / IComparable

        /// <summary>Returns true if less or equal to.</summary>
        public static bool operator <=(Length left, Length right)
        {
            return left.Value <= right.GetValueAs(left.Unit);
        }

        /// <summary>Returns true if greater than or equal to.</summary>
        public static bool operator >=(Length left, Length right)
        {
            return left.Value >= right.GetValueAs(left.Unit);
        }

        /// <summary>Returns true if less than.</summary>
        public static bool operator <(Length left, Length right)
        {
            return left.Value < right.GetValueAs(left.Unit);
        }

        /// <summary>Returns true if greater than.</summary>
        public static bool operator >(Length left, Length right)
        {
            return left.Value > right.GetValueAs(left.Unit);
        }

        /// <summary>Returns true if exactly equal.</summary>
        /// <remarks>Consider using <see cref="Equals(Length, double, ComparisonType)"/> for safely comparing floating point values.</remarks>
        public static bool operator ==(Length left, Length right)
        {
            return left.Equals(right);
        }

        /// <summary>Returns true if not exactly equal.</summary>
        /// <remarks>Consider using <see cref="Equals(Length, double, ComparisonType)"/> for safely comparing floating point values.</remarks>
        public static bool operator !=(Length left, Length right)
        {
            return !(left == right);
        }

        /// <inheritdoc />
        public int CompareTo(object obj)
        {
            if(obj is null) throw new ArgumentNullException(nameof(obj));
            if(!(obj is Length objLength)) throw new ArgumentException("Expected type Length.", nameof(obj));

            return CompareTo(objLength);
        }

        /// <inheritdoc />
        public int CompareTo(Length other)
        {
            return _value.CompareTo(other.GetValueAs(this.Unit));
        }

        /// <inheritdoc />
        /// <remarks>Consider using <see cref="Equals(Length, double, ComparisonType)"/> for safely comparing floating point values.</remarks>
        public override bool Equals(object obj)
        {
            if(obj is null || !(obj is Length objLength))
                return false;

            return Equals(objLength);
        }

        /// <inheritdoc />
        /// <remarks>Consider using <see cref="Equals(Length, double, ComparisonType)"/> for safely comparing floating point values.</remarks>
        public bool Equals(Length other)
        {
            return _value.Equals(other.GetValueAs(this.Unit));
        }

        /// <summary>
        ///     <para>
        ///     Compare equality to another Length within the given absolute or relative tolerance.
        ///     </para>
        ///     <para>
        ///     Relative tolerance is defined as the maximum allowable absolute difference between this quantity's value and
        ///     <paramref name="other"/> as a percentage of this quantity's value. <paramref name="other"/> will be converted into
        ///     this quantity's unit for comparison. A relative tolerance of 0.01 means the absolute difference must be within +/- 1% of
        ///     this quantity's value to be considered equal.
        ///     <example>
        ///     In this example, the two quantities will be equal if the value of b is within +/- 1% of a (0.02m or 2cm).
        ///     <code>
        ///     var a = Length.FromMeters(2.0);
        ///     var b = Length.FromInches(50.0);
        ///     a.Equals(b, 0.01, ComparisonType.Relative);
        ///     </code>
        ///     </example>
        ///     </para>
        ///     <para>
        ///     Absolute tolerance is defined as the maximum allowable absolute difference between this quantity's value and
        ///     <paramref name="other"/> as a fixed number in this quantity's unit. <paramref name="other"/> will be converted into
        ///     this quantity's unit for comparison.
        ///     <example>
        ///     In this example, the two quantities will be equal if the value of b is within 0.01 of a (0.01m or 1cm).
        ///     <code>
        ///     var a = Length.FromMeters(2.0);
        ///     var b = Length.FromInches(50.0);
        ///     a.Equals(b, 0.01, ComparisonType.Absolute);
        ///     </code>
        ///     </example>
        ///     </para>
        ///     <para>
        ///     Note that it is advised against specifying zero difference, due to the nature
        ///     of floating point operations and using System.Double internally.
        ///     </para>
        /// </summary>
        /// <param name="other">The other quantity to compare to.</param>
        /// <param name="tolerance">The absolute or relative tolerance value. Must be greater than or equal to 0.</param>
        /// <param name="comparisonType">The comparison type: either relative or absolute.</param>
        /// <returns>True if the absolute difference between the two values is not greater than the specified relative or absolute tolerance.</returns>
        public bool Equals(Length other, double tolerance, ComparisonType comparisonType)
        {
            if(tolerance < 0)
                throw new ArgumentOutOfRangeException("tolerance", "Tolerance must be greater than or equal to 0.");

            double thisValue = (double)this.Value;
            double otherValueInThisUnits = other.As(this.Unit);

            return UnitsNet.Comparison.Equals(thisValue, otherValueInThisUnits, tolerance, comparisonType);
        }

        /// <summary>
        ///     Returns the hash code for this instance.
        /// </summary>
        /// <returns>A hash code for the current Length.</returns>
        public override int GetHashCode()
        {
            return new { Info.Name, Value, Unit }.GetHashCode();
        }

        #endregion

        #region Conversion Methods

        /// <summary>
        ///     Convert to the unit representation <paramref name="unit" />.
        /// </summary>
        /// <returns>Value converted to the specified unit.</returns>
        public double As(LengthUnit unit)
        {
            if(Unit == unit)
                return Convert.ToDouble(Value);

            var converted = GetValueAs(unit);
            return Convert.ToDouble(converted);
        }

        /// <inheritdoc cref="IQuantity.As(UnitSystem)"/>
        public double As(UnitSystem unitSystem)
        {
            if(unitSystem is null)
                throw new ArgumentNullException(nameof(unitSystem));

            var unitInfos = Info.GetUnitInfosFor(unitSystem.BaseUnits);

            var firstUnitInfo = unitInfos.FirstOrDefault();
            if(firstUnitInfo == null)
                throw new ArgumentException("No units were found for the given UnitSystem.", nameof(unitSystem));

            return As(firstUnitInfo.Value);
        }

        /// <inheritdoc />
        double IQuantity.As(Enum unit)
        {
            if(!(unit is LengthUnit unitAsLengthUnit))
                throw new ArgumentException($"The given unit is of type {unit.GetType()}. Only {typeof(LengthUnit)} is supported.", nameof(unit));

            return As(unitAsLengthUnit);
        }

        /// <summary>
        ///     Converts this Length to another Length with the unit representation <paramref name="unit" />.
        /// </summary>
        /// <returns>A Length with the specified unit.</returns>
        public Length ToUnit(LengthUnit unit)
        {
            var convertedValue = GetValueAs(unit);
            return new Length(convertedValue, unit);
        }

        /// <inheritdoc />
        IQuantity IQuantity.ToUnit(Enum unit)
        {
            if(!(unit is LengthUnit unitAsLengthUnit))
                throw new ArgumentException($"The given unit is of type {unit.GetType()}. Only {typeof(LengthUnit)} is supported.", nameof(unit));

            return ToUnit(unitAsLengthUnit);
        }

        /// <inheritdoc cref="IQuantity.ToUnit(UnitSystem)"/>
        public Length ToUnit(UnitSystem unitSystem)
        {
            if(unitSystem is null)
                throw new ArgumentNullException(nameof(unitSystem));

            var unitInfos = Info.GetUnitInfosFor(unitSystem.BaseUnits);

            var firstUnitInfo = unitInfos.FirstOrDefault();
            if(firstUnitInfo == null)
                throw new ArgumentException("No units were found for the given UnitSystem.", nameof(unitSystem));

            return ToUnit(firstUnitInfo.Value);
        }

        /// <inheritdoc />
        IQuantity IQuantity.ToUnit(UnitSystem unitSystem) => ToUnit(unitSystem);

        /// <inheritdoc />
        IQuantity<LengthUnit> IQuantity<LengthUnit>.ToUnit(LengthUnit unit) => ToUnit(unit);

        /// <inheritdoc />
        IQuantity<LengthUnit> IQuantity<LengthUnit>.ToUnit(UnitSystem unitSystem) => ToUnit(unitSystem);

        /// <summary>
        ///     Converts the current value + unit to the base unit.
        ///     This is typically the first step in converting from one unit to another.
        /// </summary>
        /// <returns>The value in the base unit representation.</returns>
        private double GetValueInBaseUnit()
        {
            switch(Unit)
            {
                case LengthUnit.AstronomicalUnit: return _value * 1.4959787070e11;
                case LengthUnit.Centimeter: return (_value) * 1e-2d;
                case LengthUnit.Chain: return _value*20.1168;
                case LengthUnit.Decimeter: return (_value) * 1e-1d;
                case LengthUnit.DtpPica: return _value/236.220472441;
                case LengthUnit.DtpPoint: return (_value/72)*2.54e-2;
                case LengthUnit.Fathom: return _value*1.8288;
                case LengthUnit.Foot: return _value*0.3048;
                case LengthUnit.Hand: return _value * 1.016e-1;
                case LengthUnit.Hectometer: return (_value) * 1e2d;
                case LengthUnit.Inch: return _value*2.54e-2;
                case LengthUnit.KilolightYear: return (_value * 9.46073047258e15) * 1e3d;
                case LengthUnit.Kilometer: return (_value) * 1e3d;
                case LengthUnit.Kiloparsec: return (_value * 3.08567758128e16) * 1e3d;
                case LengthUnit.LightYear: return _value * 9.46073047258e15;
                case LengthUnit.MegalightYear: return (_value * 9.46073047258e15) * 1e6d;
                case LengthUnit.Megaparsec: return (_value * 3.08567758128e16) * 1e6d;
                case LengthUnit.Meter: return _value;
                case LengthUnit.Microinch: return _value*2.54e-8;
                case LengthUnit.Micrometer: return (_value) * 1e-6d;
                case LengthUnit.Mil: return _value*2.54e-5;
                case LengthUnit.Mile: return _value*1609.34;
                case LengthUnit.Millimeter: return (_value) * 1e-3d;
                case LengthUnit.Nanometer: return (_value) * 1e-9d;
                case LengthUnit.NauticalMile: return _value*1852;
                case LengthUnit.Parsec: return _value * 3.08567758128e16;
                case LengthUnit.PrinterPica: return _value/237.106301584;
                case LengthUnit.PrinterPoint: return (_value/72.27)*2.54e-2;
                case LengthUnit.Shackle: return _value*27.432;
                case LengthUnit.SolarRadius: return _value * 6.95510000E+08;
                case LengthUnit.Twip: return _value/56692.913385826;
                case LengthUnit.UsSurveyFoot: return _value*1200/3937;
                case LengthUnit.Yard: return _value*0.9144;
                default:
                    throw new NotImplementedException($"Can not convert {Unit} to base units.");
            }
        }

        /// <summary>
        ///     Converts the current value + unit to the base unit.
        ///     This is typically the first step in converting from one unit to another.
        /// </summary>
        /// <returns>The value in the base unit representation.</returns>
        internal Length ToBaseUnit()
        {
            var baseUnitValue = GetValueInBaseUnit();
            return new Length(baseUnitValue, BaseUnit);
        }

        private double GetValueAs(LengthUnit unit)
        {
            if(Unit == unit)
                return _value;

            var baseUnitValue = GetValueInBaseUnit();

            switch(unit)
            {
                case LengthUnit.AstronomicalUnit: return baseUnitValue / 1.4959787070e11;
                case LengthUnit.Centimeter: return (baseUnitValue) / 1e-2d;
                case LengthUnit.Chain: return baseUnitValue/20.1168;
                case LengthUnit.Decimeter: return (baseUnitValue) / 1e-1d;
                case LengthUnit.DtpPica: return baseUnitValue*236.220472441;
                case LengthUnit.DtpPoint: return (baseUnitValue/2.54e-2)*72;
                case LengthUnit.Fathom: return baseUnitValue/1.8288;
                case LengthUnit.Foot: return baseUnitValue/0.3048;
                case LengthUnit.Hand: return baseUnitValue / 1.016e-1;
                case LengthUnit.Hectometer: return (baseUnitValue) / 1e2d;
                case LengthUnit.Inch: return baseUnitValue/2.54e-2;
                case LengthUnit.KilolightYear: return (baseUnitValue / 9.46073047258e15) / 1e3d;
                case LengthUnit.Kilometer: return (baseUnitValue) / 1e3d;
                case LengthUnit.Kiloparsec: return (baseUnitValue / 3.08567758128e16) / 1e3d;
                case LengthUnit.LightYear: return baseUnitValue / 9.46073047258e15;
                case LengthUnit.MegalightYear: return (baseUnitValue / 9.46073047258e15) / 1e6d;
                case LengthUnit.Megaparsec: return (baseUnitValue / 3.08567758128e16) / 1e6d;
                case LengthUnit.Meter: return baseUnitValue;
                case LengthUnit.Microinch: return baseUnitValue/2.54e-8;
                case LengthUnit.Micrometer: return (baseUnitValue) / 1e-6d;
                case LengthUnit.Mil: return baseUnitValue/2.54e-5;
                case LengthUnit.Mile: return baseUnitValue/1609.34;
                case LengthUnit.Millimeter: return (baseUnitValue) / 1e-3d;
                case LengthUnit.Nanometer: return (baseUnitValue) / 1e-9d;
                case LengthUnit.NauticalMile: return baseUnitValue/1852;
                case LengthUnit.Parsec: return baseUnitValue / 3.08567758128e16;
                case LengthUnit.PrinterPica: return baseUnitValue*237.106301584;
                case LengthUnit.PrinterPoint: return (baseUnitValue/2.54e-2)*72.27;
                case LengthUnit.Shackle: return baseUnitValue/27.432;
                case LengthUnit.SolarRadius: return baseUnitValue / 6.95510000E+08;
                case LengthUnit.Twip: return baseUnitValue*56692.913385826;
                case LengthUnit.UsSurveyFoot: return baseUnitValue*3937/1200;
                case LengthUnit.Yard: return baseUnitValue/0.9144;
                default:
                    throw new NotImplementedException($"Can not convert {Unit} to {unit}.");
            }
        }

        #endregion

        #region ToString Methods

        /// <summary>
        ///     Gets the default string representation of value and unit.
        /// </summary>
        /// <returns>String representation.</returns>
        public override string ToString()
        {
            return ToString("g");
        }

        /// <summary>
        ///     Gets the default string representation of value and unit using the given format provider.
        /// </summary>
        /// <returns>String representation.</returns>
        /// <param name="provider">Format to use for localization and number formatting. Defaults to <see cref="CultureInfo.CurrentUICulture" /> if null.</param>
        public string ToString(IFormatProvider? provider)
        {
            return ToString("g", provider);
        }

        /// <summary>
        ///     Get string representation of value and unit.
        /// </summary>
        /// <param name="significantDigitsAfterRadix">The number of significant digits after the radix point.</param>
        /// <returns>String representation.</returns>
        /// <param name="provider">Format to use for localization and number formatting. Defaults to <see cref="CultureInfo.CurrentUICulture" /> if null.</param>
        [Obsolete(@"This method is deprecated and will be removed at a future release. Please use ToString(""s2"") or ToString(""s2"", provider) where 2 is an example of the number passed to significantDigitsAfterRadix.")]
        public string ToString(IFormatProvider? provider, int significantDigitsAfterRadix)
        {
            var value = Convert.ToDouble(Value);
            var format = UnitFormatter.GetFormat(value, significantDigitsAfterRadix);
            return ToString(provider, format);
        }

        /// <summary>
        ///     Get string representation of value and unit.
        /// </summary>
        /// <param name="format">String format to use. Default:  "{0:0.##} {1} for value and unit abbreviation respectively."</param>
        /// <param name="args">Arguments for string format. Value and unit are implicitly included as arguments 0 and 1.</param>
        /// <returns>String representation.</returns>
        /// <param name="provider">Format to use for localization and number formatting. Defaults to <see cref="CultureInfo.CurrentUICulture" /> if null.</param>
        [Obsolete("This method is deprecated and will be removed at a future release. Please use string.Format().")]
        public string ToString(IFormatProvider? provider, [NotNull] string format, [NotNull] params object[] args)
        {
            if (format == null) throw new ArgumentNullException(nameof(format));
            if (args == null) throw new ArgumentNullException(nameof(args));

            provider = provider ?? CultureInfo.CurrentUICulture;

            var value = Convert.ToDouble(Value);
            var formatArgs = UnitFormatter.GetFormatArgs(Unit, value, provider, args);
            return string.Format(provider, format, formatArgs);
        }

        /// <inheritdoc cref="QuantityFormatter.Format{TUnitType}(IQuantity{TUnitType}, string, IFormatProvider)"/>
        /// <summary>
        /// Gets the string representation of this instance in the specified format string using <see cref="CultureInfo.CurrentUICulture" />.
        /// </summary>
        /// <param name="format">The format string.</param>
        /// <returns>The string representation.</returns>
        public string ToString(string format)
        {
            return ToString(format, CultureInfo.CurrentUICulture);
        }

        /// <inheritdoc cref="QuantityFormatter.Format{TUnitType}(IQuantity{TUnitType}, string, IFormatProvider)"/>
        /// <summary>
        /// Gets the string representation of this instance in the specified format string using the specified format provider, or <see cref="CultureInfo.CurrentUICulture" /> if null.
        /// </summary>
        /// <param name="format">The format string.</param>
        /// <param name="provider">Format to use for localization and number formatting. Defaults to <see cref="CultureInfo.CurrentUICulture" /> if null.</param>
        /// <returns>The string representation.</returns>
        public string ToString(string format, IFormatProvider? provider)
        {
            return QuantityFormatter.Format<LengthUnit>(this, format, provider);
        }

        #endregion

        #region IConvertible Methods

        TypeCode IConvertible.GetTypeCode()
        {
            return TypeCode.Object;
        }

        bool IConvertible.ToBoolean(IFormatProvider provider)
        {
            throw new InvalidCastException($"Converting {typeof(Length)} to bool is not supported.");
        }

        byte IConvertible.ToByte(IFormatProvider provider)
        {
            return Convert.ToByte(_value);
        }

        char IConvertible.ToChar(IFormatProvider provider)
        {
            throw new InvalidCastException($"Converting {typeof(Length)} to char is not supported.");
        }

        DateTime IConvertible.ToDateTime(IFormatProvider provider)
        {
            throw new InvalidCastException($"Converting {typeof(Length)} to DateTime is not supported.");
        }

        decimal IConvertible.ToDecimal(IFormatProvider provider)
        {
            return Convert.ToDecimal(_value);
        }

        double IConvertible.ToDouble(IFormatProvider provider)
        {
            return Convert.ToDouble(_value);
        }

        short IConvertible.ToInt16(IFormatProvider provider)
        {
            return Convert.ToInt16(_value);
        }

        int IConvertible.ToInt32(IFormatProvider provider)
        {
            return Convert.ToInt32(_value);
        }

        long IConvertible.ToInt64(IFormatProvider provider)
        {
            return Convert.ToInt64(_value);
        }

        sbyte IConvertible.ToSByte(IFormatProvider provider)
        {
            return Convert.ToSByte(_value);
        }

        float IConvertible.ToSingle(IFormatProvider provider)
        {
            return Convert.ToSingle(_value);
        }

        string IConvertible.ToString(IFormatProvider provider)
        {
            return ToString("g", provider);
        }

        object IConvertible.ToType(Type conversionType, IFormatProvider provider)
        {
            if(conversionType == typeof(Length))
                return this;
            else if(conversionType == typeof(LengthUnit))
                return Unit;
            else if(conversionType == typeof(QuantityType))
                return Length.QuantityType;
            else if(conversionType == typeof(QuantityInfo))
                return Length.Info;
            else if(conversionType == typeof(BaseDimensions))
                return Length.BaseDimensions;
            else
                throw new InvalidCastException($"Converting {typeof(Length)} to {conversionType} is not supported.");
        }

        ushort IConvertible.ToUInt16(IFormatProvider provider)
        {
            return Convert.ToUInt16(_value);
        }

        uint IConvertible.ToUInt32(IFormatProvider provider)
        {
            return Convert.ToUInt32(_value);
        }

        ulong IConvertible.ToUInt64(IFormatProvider provider)
        {
            return Convert.ToUInt64(_value);
        }

        #endregion
    }
}
