Skip to content

Instantly share code, notes, and snippets.

@josheinstein
Created May 18, 2012 16:15
Show Gist options
  • Save josheinstein/2726144 to your computer and use it in GitHub Desktop.
Save josheinstein/2726144 to your computer and use it in GitHub Desktop.
DataSize Class (C#)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml.Serialization;
namespace Einstein
{
/// <summary>
/// A structure for representing sizes in bytes, KB, MB, etc while retaining the full value type
/// nature of a native structure. A value of type DataSize sorts correctly in lists, chooses its
/// unit automatically similar to how Windows Explorer does, and can be used with standard
/// operators such as adding, subtracting, greater than/less than, etc. It can be quickly and
/// implicitly cast to and from bytes (Int64) and implements various interfaces that make it
/// nearly a first-class data structure like DateTime.
/// </summary>
[Serializable]
public struct DataSize : IFormattable, IComparable<DataSize>, IComparable, IConvertible, IEquatable<DataSize>, IXmlSerializable
{
#region Constants
/// <summary>
/// The size of a byte, in bytes. Always 1, provided for consistency only.
/// </summary>
public const long ByteSize = 1L;
/// <summary>
/// The size of a kilobyte, in bytes. This structure defines a KB as 1,024 bytes.
/// </summary>
public const long KilobyteSize = 1024L;
/// <summary>
/// The size of a megabyte, in bytes. This structure defines a MB as 1,024^2 or 1,048,576 bytes.
/// </summary>
public const long MegabyteSize = 1024L * 1024L;
/// <summary>
/// The size of a gigabyte, in bytes. This structure defines a GB as 1,024^3 or 1,073,741,824 bytes.
/// </summary>
public const long GigabyteSize = 1024L * 1024L * 1024L;
/// <summary>
/// The size of a terabyte, in bytes. This structure defines a TB as 1,024^4 or 1,099,511,627,776 bytes.
/// </summary>
public const long TerabyteSize = 1024L * 1024L * 1024L * 1024L;
/// <summary>
/// The suffix appended to the end of a string represented as bytes.
/// </summary>
public const string ByteSuffix = "B";
/// <summary>
/// The suffix appended to the end of a string represented as kilobytes.
/// </summary>
public const string KilobyteSuffix = "KB";
/// <summary>
/// The suffix appended to the end of a string represented as megabytes.
/// </summary>
public const string MegabyteSuffix = "MB";
/// <summary>
/// The suffix appended to the end of a string represented as gigabytes.
/// </summary>
public const string GigabyteSuffix = "GB";
/// <summary>
/// The suffix appended to the end of a string represented as terabytes.
/// </summary>
public const string TerabyteSuffix = "TB";
#endregion
#region Fields
/// <summary>
/// Holds the value of the data size, in bytes.
/// </summary>
private long bytes;
/// <summary>
/// Regular expression used to pick apart the format string.
/// </summary>
private static readonly Regex formatRegex = new Regex( @"(?<unit>A|B|K|M|G|T)(?<precision>\d+)?(?<nosuffix>\*)?", RegexOptions.ExplicitCapture | RegexOptions.IgnoreCase | RegexOptions.Singleline );
#endregion
#region Constructors
/// <summary>
/// Creates a new DataSize representing the specified number of bytes.
/// </summary>
public DataSize( long bytes )
{
this.bytes = bytes;
}
#endregion
#region Properties
/// <summary>
/// Gets the value in terabytes.
/// </summary>
public decimal TotalTerabytes
{
get
{
return bytes / (decimal)TerabyteSize;
}
}
/// <summary>
/// Gets the value in gigabytes.
/// </summary>
public decimal TotalGigabytes
{
get
{
return bytes / (decimal)GigabyteSize;
}
}
/// <summary>
/// Gets the value in megabytes.
/// </summary>
public decimal TotalMegabytes
{
get
{
return bytes / (decimal)MegabyteSize;
}
}
/// <summary>
/// Gets the value in kilobytes.
/// </summary>
public decimal TotalKilobytes
{
get
{
return bytes / (decimal)KilobyteSize;
}
}
/// <summary>
/// Gets the value in bytes.
/// </summary>
public decimal TotalBytes
{
get
{
return (decimal)bytes;
}
}
/// <summary>
/// Gets the value in bytes as a signed 64 bit integer.
/// </summary>
public long Bytes
{
get
{
return bytes;
}
}
#endregion
#region Methods
/// <summary>
/// Converts the String representation of a number to its DataSize equivalent. A return value indicates whether the conversion succeeded or failed.
/// </summary>
/// <remarks>
/// <para>
/// The string can take on the format of:
/// <list type="bullet">
/// <item>128 MB</item>
/// <item>40.00 KB</item>
/// <item>78 gigabytes</item>
/// <item>1 terabyte</item>
/// </list>
/// </para>
/// <para>
/// Lowercase representations will be accepted such as a b, kb, mb, etc but they will not be treated as "bits" they
/// will be treated as "bytes". Their acceptance is simply to keep the function case insensitive.
/// </para>
/// </remarks>
/// <param name="input">A String object containing a data size to convert.</param>
/// <returns>A DataSize structure representing the specified string.</returns>
public static DataSize Parse( string input )
{
if ( input == null )
throw new ArgumentNullException( "input" );
DataSize dataSize;
if ( TryParse( input, out dataSize ) )
return dataSize;
else
throw new FormatException( "Could not parse the specified string into a DataSize." );
}
/// <summary>
/// Converts the String representation of a number to its DataSize equivalent. A return value indicates whether the conversion succeeded or failed.
/// </summary>
/// <param name="input">A String object containing a number to convert.</param>
/// <param name="dataSize">When this method returns, contains DatSize equivalent to the numeric value or symbol contained
/// in input, if the conversion succeeded, or zero if the conversion failed. The conversion fails if the input parameter is a null
/// reference (Nothing in Visual Basic), is not a number in a valid format, or represents a number less than MinValue or greater than MaxValue. This
/// parameter is passed uninitialized.</param>
/// <returns>
/// True if the parse succeeded, false otherwise.
/// </returns>
/// <remarks>
/// <para>
/// The string can take on the format of:
/// <list type="bullet">
/// <item>128 MB</item>
/// <item>40.00 KB</item>
/// <item>78 gigabytes</item>
/// <item>1 terabyte</item>
/// </list>
/// </para>
/// <para>
/// Lowercase representations will be accepted such as a b, kb, mb, etc but they will not be treated as "bits" they
/// will be treated as "bytes". Their acceptance is simply to keep the function case insensitive.
/// </para>
/// </remarks>
public static bool TryParse( string input, out DataSize dataSize )
{
return TryParse( input, false, out dataSize );
}
/// <summary>
/// Converts the String representation of a number to its DataSize equivalent. A return value indicates whether the conversion succeeded or failed.
/// </summary>
/// <param name="input">A String object containing a number to convert.</param>
/// <param name="requireUnit">True if a data size unit is required for the parse to succeed, false otherwise.</param>
/// <param name="dataSize">When this method returns, contains DatSize equivalent to the numeric value or symbol contained
/// in input, if the conversion succeeded, or zero if the conversion failed. The conversion fails if the input parameter is a null
/// reference (Nothing in Visual Basic), is not a number in a valid format, or represents a number less than MinValue or greater than MaxValue. This
/// parameter is passed uninitialized.</param>
/// <returns>
/// True if the parse succeeded, false otherwise.
/// </returns>
/// <remarks>
/// <para>
/// The string can take on the format of:
/// <list type="bullet">
/// <item>128 MB</item>
/// <item>40.00 KB</item>
/// <item>78 gigabytes</item>
/// <item>1 terabyte</item>
/// </list>
/// </para>
/// <para>
/// Lowercase representations will be accepted such as a b, kb, mb, etc but they will not be treated as "bits" they
/// will be treated as "bytes". Their acceptance is simply to keep the function case insensitive.
/// </para>
/// </remarks>
[SuppressMessage( "Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification = "The switch statement is throwing it off." )]
public static bool TryParse( string input, bool requireUnit, out DataSize dataSize )
{
dataSize = default( DataSize );
// Make sure we have a string
if ( String.IsNullOrEmpty( input ) )
return false;
// Trim both ends of input
input = input.Trim( );
string numberPart = null;
string unitPart = null;
// Find the position of the space, if any
int spacePos = input.IndexOf( ' ' );
if ( spacePos > -1 ) {
// A space exists in the string
// First segment is the number such as 3.04
// Second segment is assumed to be the unit such as KB
numberPart = input.Substring( 0, spacePos ).Trim( );
unitPart = input.Substring( spacePos + 1 ).Trim( );
}
else {
if ( requireUnit ) {
return false;
}
else {
numberPart = input;
unitPart = "B";
}
}
// Parse the number into a decimal. Allow separators and such
// If the parse fails, an exception will be thrown which will
// propagate out to the caller.
decimal number = 0m;
if ( Decimal.TryParse( numberPart, NumberStyles.Number, null, out number ) ) {
#region B.A.S.S. - Big Ass Switch Statement
switch ( unitPart.ToUpper( CultureInfo.InvariantCulture ) ) {
case "B":
case "BYTE":
case "BYTES":
break;
case "K":
case "KB":
case "KBYTE":
case "KBYTES":
case "KILOBYTE":
case "KILOBYTES":
number *= KilobyteSize;
break;
case "M":
case "MB":
case "MEG":
case "MEGS":
case "MBYTE":
case "MBYTES":
case "MEGABYTE":
case "MEGABYTES":
number *= MegabyteSize;
break;
case "G":
case "GB":
case "GIG":
case "GIGS":
case "GBYTE":
case "GBYTES":
case "GIGABYTE":
case "GIGABYTES":
number *= GigabyteSize;
break;
case "T":
case "TB":
case "TBYTE":
case "TBYTES":
case "TERABYTE":
case "TERABYTES":
number *= TerabyteSize;
break;
default:
return false;
}
#endregion
dataSize = new DataSize( (long)number );
return true;
}
return false;
}
/// <summary>
/// Compares two DataSize structures and returns a value indicating whether one is less
/// than, equal to, or greater than the other.
/// </summary>
/// <param name="x">The first DataSize to compare.</param>
/// <param name="y">The second DataSize to compare.</param>
/// <returns>
/// Less than zero, x is less than y. Zero, x equals y. Greater than zero, x is greater than y.
/// </returns>
[SuppressMessage( "Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "x" )]
[SuppressMessage( "Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "y" )]
public static int Compare( DataSize x, DataSize y )
{
return x.CompareTo( y );
}
/// <summary>
/// Determines of two DataSize values are equal.
/// </summary>
/// <param name="x">The first DataSize to compare.</param>
/// <param name="y">The second DataSize to compare.</param>
/// <returns>True if the values are equal, false otherwise.</returns>
[SuppressMessage( "Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "x" )]
[SuppressMessage( "Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "y" )]
public static bool Equals( DataSize x, DataSize y )
{
return x.Equals( y );
}
#endregion
#region Object Overrides
/// <summary>
/// Indicates whether this instance and a specified object are equal.
/// </summary>
/// <param name="obj">Another object to compare to.</param>
/// <returns>
/// true if obj and this instance are the same type and represent the same value; otherwise, false.
/// </returns>
public override bool Equals( object obj )
{
if ( obj is DataSize )
return Equals( (DataSize)obj );
else
return false;
}
/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns>
/// A 32-bit signed integer that is the hash code for this instance.
/// </returns>
public override int GetHashCode( )
{
return bytes.GetHashCode( );
}
/// <summary>
/// Returns a string representation of this DataSize using the default format.
/// </summary>
/// <returns>
/// A <see cref="T:String"></see> representing this data size.
/// </returns>
public override string ToString( )
{
return ToString( "A", CultureInfo.CurrentCulture );
}
/// <summary>
/// Returns a string representation of this DataSize using the default format.
/// </summary>
/// <param name="format">The format.</param>
/// <returns>
/// A <see cref="T:String"></see> representing this data size.
/// </returns>
/// <remarks>
/// <para>
/// The format specifier takes the form of: A99*
/// </para>
/// <para>
/// Where A is any of the following characters:
/// <list type="table">
/// <listheader><term>Format Character</term></listheader>
/// <item><term>A</term><description>Automatic. The unit of measurement will be the largest unit that is greater than or equal to 1.</description></item>
/// <item><term>B</term><description>Bytes (B). No decimal digits will ever be displayed.</description></item>
/// <item><term>K</term><description>Kilobytes (KB)</description></item>
/// <item><term>M</term><description>Megabytes (MB)</description></item>
/// <item><term>G</term><description>Gigabytes (GB)</description></item>
/// <item><term>T</term><description>Terabytes (TB)</description></item>
/// </list>
/// </para>
/// <para>
/// The 99 represent a number from 0-99 that indicates the number of decimal places that will be
/// included in the string. If bytes are specified as the unit of measurement, no decimal places will
/// ever be used and this part of the format string will be ignored. If the precision is missing, up
/// to two decimal places will be used.
/// </para>
/// <para>
/// The asterisk (*) is an optional indicator that supresses the suffix. For example, if the value 39 KB
/// is formatted as "K2*" then the output string would be "39.00" instead of "39.00 KB" because of the
/// asterisk.
/// </para>
/// </remarks>
public string ToString( string format )
{
return ToString( format, CultureInfo.CurrentCulture );
}
#endregion
#region Operator Overloads
/// <summary>
/// Equality operator.
/// </summary>
/// <param name="left">The first DataSize to compare.</param>
/// <param name="right">The second DataSize to compare.</param>
/// <returns>True if <paramref name="left"/> and <paramref name="right"/> are equal, false otherwise.</returns>
public static bool operator ==( DataSize left, DataSize right )
{
return left.bytes == right.bytes;
}
/// <summary>
/// Inequality operator.
/// </summary>
/// <param name="left">The first DataSize to compare.</param>
/// <param name="right">The second DataSize to compare.</param>
/// <returns>False if <paramref name="left"/> and <paramref name="right"/> are equal, true otherwise.</returns>
public static bool operator !=( DataSize left, DataSize right )
{
return left.bytes != right.bytes;
}
/// <summary>
/// Greater than operator.
/// </summary>
/// <param name="left">The first DataSize to compare.</param>
/// <param name="right">The second DataSize to compare.</param>
/// <returns>True if <paramref name="left"/> is greater than <paramref name="right"/>, false otherwise.</returns>
public static bool operator >( DataSize left, DataSize right )
{
return left.bytes > right.bytes;
}
/// <summary>
/// Less than operator.
/// </summary>
/// <param name="left">The first DataSize to compare.</param>
/// <param name="right">The second DataSize to compare.</param>
/// <returns>True if <paramref name="left"/> is less than <paramref name="right"/>, false otherwise.</returns>
public static bool operator <( DataSize left, DataSize right )
{
return left.bytes < right.bytes;
}
/// <summary>
/// Greater than or equals operator.
/// </summary>
/// <param name="left">The first DataSize to compare.</param>
/// <param name="right">The second DataSize to compare.</param>
/// <returns>True if <paramref name="left"/> is greater than or equals <paramref name="right"/>, false otherwise.</returns>
public static bool operator >=( DataSize left, DataSize right )
{
return left.bytes >= right.bytes;
}
/// <summary>
/// Less than or equals operator.
/// </summary>
/// <param name="left">The first DataSize to compare.</param>
/// <param name="right">The second DataSize to compare.</param>
/// <returns>True if <paramref name="left"/> is less than or equals <paramref name="right"/>, false otherwise.</returns>
public static bool operator <=( DataSize left, DataSize right )
{
return left.bytes <= right.bytes;
}
/// <summary>
/// Unary plus operator.
/// </summary>
/// <param name="operand">The operand on which the operator operates.</param>
/// <returns>The <paramref name="operand"/>.</returns>
public static DataSize operator +( DataSize operand )
{
return operand;
}
/// <summary>
/// Unary negation operator.
/// </summary>
/// <param name="operand">The operand on which the operator operates.</param>
/// <returns>The <paramref name="operand"/>, negated.</returns>
public static DataSize operator -( DataSize operand )
{
return new DataSize( -( operand.bytes ) );
}
/// <summary>
/// Unary increment operator.
/// </summary>
/// <param name="operand">The operand on which the operator operates.</param>
/// <returns>The <paramref name="operand"/> plus one.</returns>
public static DataSize operator ++( DataSize operand )
{
return new DataSize( operand.bytes + 1 );
}
/// <summary>
/// Unary decrement operator.
/// </summary>
/// <param name="operand">The operand on which the operator operates.</param>
/// <returns>The <paramref name="operand"/>, minus one.</returns>
public static DataSize operator --( DataSize operand )
{
return new DataSize( operand.bytes - 1 );
}
/// <summary>
/// Addition operator.
/// </summary>
/// <param name="left">A DataSize to which <paramref name="right"/> will be added.</param>
/// <param name="right">A second DataSize to add to <paramref name="left"/>.</param>
/// <returns>A datasize that is the sum of <paramref name="left"/> and <paramref name="right"/>.</returns>
public static DataSize operator +( DataSize left, DataSize right )
{
return new DataSize( left.bytes + right.bytes );
}
/// <summary>
/// Subtraction operator.
/// </summary>
/// <param name="left">A DataSize to which <paramref name="right"/> will be subtracted.</param>
/// <param name="right">A second DataSize to subtract from <paramref name="left"/>.</param>
/// <returns>A datasize that is the difference of <paramref name="left"/> and <paramref name="right"/>.</returns>
public static DataSize operator -( DataSize left, DataSize right )
{
return new DataSize( left.bytes - right.bytes );
}
/// <summary>
/// Multiplication operator.
/// </summary>
/// <param name="left">A DataSize which will be multiplied by <paramref name="right"/>.</param>
/// <param name="right">A DataSize by which <paramref name="left"/> will be multiplied.</param>
/// <returns>A datasize that is the result of <paramref name="left"/> multiplied by <paramref name="right"/>.</returns>
public static DataSize operator *( DataSize left, DataSize right )
{
return new DataSize( left.bytes * right.bytes );
}
/// <summary>
/// Division operator.
/// </summary>
/// <param name="left">A DataSize which will be divided by <paramref name="right"/>.</param>
/// <param name="right">A DataSize by which <paramref name="left"/> will be divided.</param>
/// <returns>A datasize that is the result of <paramref name="left"/> divided by <paramref name="right"/>.</returns>
public static DataSize operator /( DataSize left, DataSize right )
{
return new DataSize( left.bytes / right.bytes );
}
#endregion
#region Conversion Operators
/// <summary>
/// Implicitly converts the specified <paramref name="operand"/> to <see cref="Int64"/>.
/// </summary>
/// <param name="operand">The DataSize to convert.</param>
/// <returns>An <see cref="Int64"/> value that is the number of bytes represented by
/// <paramref name="operand"/>.</returns>
public static implicit operator long( DataSize operand )
{
return operand.bytes;
}
/// <summary>
/// Implicitly converts the specified <paramref name="operand"/> to <see cref="Decimal"/>.
/// </summary>
/// <param name="operand">The DataSize to convert.</param>
/// <returns>A <see cref="Decimal"/> value that is the number of bytes represented by
/// <paramref name="operand"/>.</returns>
public static implicit operator decimal( DataSize operand )
{
return operand.TotalBytes;
}
/// <summary>
/// Explicitly converts the specified <paramref name="operand"/> to <see cref="DataSize"/>.
/// </summary>
/// <param name="operand">The <see cref="Int64"/> to convert.</param>
/// <returns>A <see cref="DataSize"/> value that represents <paramref name="operand"/>
/// number of bytes.</returns>
[SuppressMessage( "Microsoft.Interoperability", "CA1406:AvoidInt64ArgumentsForVB6Clients", Justification = "VB 6 can't use overloaded operators." )]
public static explicit operator DataSize( long operand )
{
return new DataSize( operand );
}
/// <summary>
/// Explicitly converts the specified <paramref name="operand"/> to a string.
/// </summary>
/// <param name="operand">The <see cref="DataSize"/> to convert.</param>
/// <returns>
/// A string value that is the same as <see cref="M:ToString"/>.
/// </returns>
public static explicit operator string( DataSize operand )
{
return operand.ToString( );
}
#endregion
#region IFormattable Members
/// <summary>
/// Formats the value of the current instance using the specified format.
/// </summary>
/// <param name="format">The <see cref="T:String"></see> specifying the format to use.-or- null to use the default format defined for the type of the <see cref="T:IFormattable"></see> implementation.</param>
/// <param name="formatProvider">The <see cref="T:IFormatProvider"></see> to use to format the value.-or- null to obtain the numeric format information from the current locale setting of the operating system.</param>
/// <returns>
/// A <see cref="T:String"></see> containing the value of the current instance in the specified format.
/// </returns>
public string ToString( string format, IFormatProvider formatProvider )
{
if ( String.IsNullOrEmpty( format ) ) {
format = "A";
}
Match formatMatch = formatRegex.Match( format );
if ( formatMatch.Success ) {
decimal value;
int precision;
string suffix;
// Parse the precision specifier which determines how many decimal digits
// will be displayed in the number portion of the return value.
if ( formatMatch.Groups["precision"].Success ) {
// Try to parse the precision specifier and if we can't, default to zero
if ( Int32.TryParse( formatMatch.Groups["precision"].Value, out precision ) ) {
if ( precision > 99 || precision < 0 ) {
throw new FormatException( "Invalid format specifier." );
}
}
else {
throw new FormatException( "Invalid format specifier." );
}
}
else {
precision = 2;
}
switch ( formatMatch.Groups["unit"].Value.ToUpper( CultureInfo.InvariantCulture ) ) {
case "A": {
// Automatic based on the size of the value
if ( Decimal.Truncate( Math.Abs( TotalTerabytes ) ) >= 1 ) {
goto case "T";
}
else if ( Decimal.Truncate( Math.Abs( TotalGigabytes ) ) >= 1 ) {
goto case "G";
}
else if ( Decimal.Truncate( Math.Abs( TotalMegabytes ) ) >= 1 ) {
goto case "M";
}
else if ( Decimal.Truncate( Math.Abs( TotalKilobytes ) ) >= 1 ) {
goto case "K";
}
else {
goto case "B";
}
}
case "B": {
value = TotalBytes;
suffix = ByteSuffix;
precision = 0; // bytes cannot be fractional
break;
}
case "K": {
value = TotalKilobytes;
suffix = KilobyteSuffix;
break;
}
case "M": {
value = TotalMegabytes;
suffix = MegabyteSuffix;
break;
}
case "G": {
value = TotalGigabytes;
suffix = GigabyteSuffix;
break;
}
case "T": {
value = TotalTerabytes;
suffix = TerabyteSuffix;
break;
}
default: {
throw new FormatException( "Invalid format specifier." );
}
}
if ( formatMatch.Groups["nosuffix"].Success ) {
// They want the value without the suffix
return String.Format( formatProvider, "{0:N" + precision + "}", value );
}
else {
// They want the value with the sufffix
return String.Format( formatProvider, "{0:N" + precision + "} {1}", value, suffix );
}
}
else {
throw new FormatException( "Invalid format specifier." );
}
}
#endregion
#region IComparable<DataSize> Members
/// <summary>
/// Compares the current object with another object of the same type.
/// </summary>
/// <param name="other">An object to compare with this object.</param>
/// <returns>
/// A 32-bit signed integer that indicates the relative order of the objects being compared. The return value has the following meanings: Value Meaning Less than zero This object is less than the other parameter.Zero This object is equal to other. Greater than zero This object is greater than other.
/// </returns>
public int CompareTo( DataSize other )
{
return bytes.CompareTo( other.bytes );
}
#endregion
#region IComparable Members
/// <summary>
/// Compares the current instance with another object of the same type.
/// </summary>
/// <param name="obj">An object to compare with this instance.</param>
/// <returns>
/// A 32-bit signed integer that indicates the relative order of the objects being compared. The return value has these meanings: Value Meaning Less than zero This instance is less than obj. Zero This instance is equal to obj. Greater than zero This instance is greater than obj.
/// </returns>
/// <exception cref="T:ArgumentException">obj is not the same type as this instance. </exception>
public int CompareTo( object obj )
{
if ( obj is DataSize ) {
return CompareTo( (DataSize)obj );
}
else {
throw new ArgumentException( "Compared value is not a DataSize.", "obj" );
}
}
#endregion
#region IConvertible Members
/// <summary>
/// Returns the <see cref="T:TypeCode"></see> for this instance.
/// </summary>
/// <returns>
/// The enumerated constant that is the <see cref="T:TypeCode"></see> of the class or value type that implements this interface.
/// </returns>
TypeCode IConvertible.GetTypeCode( )
{
return TypeCode.Int64;
}
/// <summary>
/// Converts the value of this instance to an equivalent Boolean value using the specified culture-specific formatting information.
/// </summary>
/// <param name="provider">An <see cref="T:IFormatProvider"></see> interface implementation that supplies culture-specific formatting information.</param>
/// <returns>
/// A Boolean value equivalent to the value of this instance.
/// </returns>
bool IConvertible.ToBoolean( IFormatProvider provider )
{
return ( bytes != 0 );
}
/// <summary>
/// Converts the value of this instance to an equivalent 8-bit unsigned integer using the specified culture-specific formatting information.
/// </summary>
/// <param name="provider">An <see cref="T:IFormatProvider"></see> interface implementation that supplies culture-specific formatting information.</param>
/// <returns>
/// An 8-bit unsigned integer equivalent to the value of this instance.
/// </returns>
byte IConvertible.ToByte( IFormatProvider provider )
{
return (byte)bytes;
}
/// <summary>
/// Converts the value of this instance to an equivalent Unicode character using the specified culture-specific formatting information.
/// </summary>
/// <param name="provider">An <see cref="T:IFormatProvider"></see> interface implementation that supplies culture-specific formatting information.</param>
/// <returns>
/// A Unicode character equivalent to the value of this instance.
/// </returns>
char IConvertible.ToChar( IFormatProvider provider )
{
throw new InvalidCastException( "Cannot convert from Einstein.DataSize to System.Char." );
}
/// <summary>
/// Converts the value of this instance to an equivalent <see cref="T:DateTime"></see> using the specified culture-specific formatting information.
/// </summary>
/// <param name="provider">An <see cref="T:IFormatProvider"></see> interface implementation that supplies culture-specific formatting information.</param>
/// <returns>
/// A <see cref="T:DateTime"></see> instance equivalent to the value of this instance.
/// </returns>
DateTime IConvertible.ToDateTime( IFormatProvider provider )
{
throw new InvalidCastException( "Cannot convert from Einstein.DataSize to System.DateTime." );
}
/// <summary>
/// Converts the value of this instance to an equivalent <see cref="T:Decimal"></see> number using the specified culture-specific formatting information.
/// </summary>
/// <param name="provider">An <see cref="T:IFormatProvider"></see> interface implementation that supplies culture-specific formatting information.</param>
/// <returns>
/// A <see cref="T:Decimal"></see> number equivalent to the value of this instance.
/// </returns>
decimal IConvertible.ToDecimal( IFormatProvider provider )
{
return (decimal)bytes;
}
/// <summary>
/// Converts the value of this instance to an equivalent double-precision floating-point number using the specified culture-specific formatting information.
/// </summary>
/// <param name="provider">An <see cref="T:IFormatProvider"></see> interface implementation that supplies culture-specific formatting information.</param>
/// <returns>
/// A double-precision floating-point number equivalent to the value of this instance.
/// </returns>
double IConvertible.ToDouble( IFormatProvider provider )
{
return (double)bytes;
}
/// <summary>
/// Converts the value of this instance to an equivalent 16-bit signed integer using the specified culture-specific formatting information.
/// </summary>
/// <param name="provider">An <see cref="T:IFormatProvider"></see> interface implementation that supplies culture-specific formatting information.</param>
/// <returns>
/// An 16-bit signed integer equivalent to the value of this instance.
/// </returns>
short IConvertible.ToInt16( IFormatProvider provider )
{
return (short)bytes;
}
/// <summary>
/// Converts the value of this instance to an equivalent 32-bit signed integer using the specified culture-specific formatting information.
/// </summary>
/// <param name="provider">An <see cref="T:IFormatProvider"></see> interface implementation that supplies culture-specific formatting information.</param>
/// <returns>
/// An 32-bit signed integer equivalent to the value of this instance.
/// </returns>
int IConvertible.ToInt32( IFormatProvider provider )
{
return (int)bytes;
}
/// <summary>
/// Converts the value of this instance to an equivalent 64-bit signed integer using the specified culture-specific formatting information.
/// </summary>
/// <param name="provider">An <see cref="T:IFormatProvider"></see> interface implementation that supplies culture-specific formatting information.</param>
/// <returns>
/// An 64-bit signed integer equivalent to the value of this instance.
/// </returns>
long IConvertible.ToInt64( IFormatProvider provider )
{
return bytes;
}
/// <summary>
/// Converts the value of this instance to an equivalent 8-bit signed integer using the specified culture-specific formatting information.
/// </summary>
/// <param name="provider">An <see cref="T:IFormatProvider"></see> interface implementation that supplies culture-specific formatting information.</param>
/// <returns>
/// An 8-bit signed integer equivalent to the value of this instance.
/// </returns>
sbyte IConvertible.ToSByte( IFormatProvider provider )
{
return (sbyte)bytes;
}
/// <summary>
/// Converts the value of this instance to an equivalent single-precision floating-point number using the specified culture-specific formatting information.
/// </summary>
/// <param name="provider">An <see cref="T:IFormatProvider"></see> interface implementation that supplies culture-specific formatting information.</param>
/// <returns>
/// A single-precision floating-point number equivalent to the value of this instance.
/// </returns>
float IConvertible.ToSingle( IFormatProvider provider )
{
return (float)bytes;
}
/// <summary>
/// Converts the value of this instance to an equivalent <see cref="T:String"></see> using the specified culture-specific formatting information.
/// </summary>
/// <param name="provider">An <see cref="T:IFormatProvider"></see> interface implementation that supplies culture-specific formatting information.</param>
/// <returns>
/// A <see cref="T:String"></see> instance equivalent to the value of this instance.
/// </returns>
string IConvertible.ToString( IFormatProvider provider )
{
return ToString( "A", provider );
}
/// <summary>
/// Converts the value of this instance to an <see cref="T:Object"></see> of the specified <see cref="T:Type"></see> that has an equivalent value, using the specified culture-specific formatting information.
/// </summary>
/// <param name="conversionType">The <see cref="T:Type"></see> to which the value of this instance is converted.</param>
/// <param name="provider">An <see cref="T:IFormatProvider"></see> interface implementation that supplies culture-specific formatting information.</param>
/// <returns>
/// An <see cref="T:Object"></see> instance of type conversionType whose value is equivalent to the value of this instance.
/// </returns>
object IConvertible.ToType( Type conversionType, IFormatProvider provider )
{
IConvertible convertible = this;
if ( conversionType == typeof( string ) ) {
return convertible.ToString( provider );
}
if ( conversionType == typeof( DataSize ) ) {
return this;
}
if ( conversionType == typeof( uint ) ) {
return convertible.ToUInt32( provider );
}
if ( conversionType == typeof( int ) ) {
return convertible.ToInt32( provider );
}
if ( conversionType == typeof( ulong ) ) {
return convertible.ToUInt64( provider );
}
if ( conversionType == typeof( long ) ) {
return convertible.ToInt64( provider );
}
if ( conversionType == typeof( float ) ) {
return convertible.ToSingle( provider );
}
if ( conversionType == typeof( double ) ) {
return convertible.ToDouble( provider );
}
if ( conversionType == typeof( decimal ) ) {
return convertible.ToDecimal( provider );
}
if ( conversionType == typeof( byte ) ) {
return convertible.ToByte( provider );
}
if ( conversionType == typeof( sbyte ) ) {
return convertible.ToSByte( provider );
}
if ( conversionType == typeof( ushort ) ) {
return convertible.ToUInt16( provider );
}
if ( conversionType == typeof( short ) ) {
return convertible.ToInt16( provider );
}
if ( conversionType == typeof( bool ) ) {
return convertible.ToBoolean( provider );
}
if ( conversionType == typeof( DateTime ) ) {
return convertible.ToDateTime( provider );
}
if ( conversionType == typeof( char ) ) {
return convertible.ToChar( provider );
}
throw new InvalidCastException( "Unable to convert DataSize to the requested type." );
}
/// <summary>
/// Converts the value of this instance to an equivalent 16-bit unsigned integer using the specified culture-specific formatting information.
/// </summary>
/// <param name="provider">An <see cref="T:IFormatProvider"></see> interface implementation that supplies culture-specific formatting information.</param>
/// <returns>
/// An 16-bit unsigned integer equivalent to the value of this instance.
/// </returns>
ushort IConvertible.ToUInt16( IFormatProvider provider )
{
return (ushort)bytes;
}
/// <summary>
/// Converts the value of this instance to an equivalent 32-bit unsigned integer using the specified culture-specific formatting information.
/// </summary>
/// <param name="provider">An <see cref="T:IFormatProvider"></see> interface implementation that supplies culture-specific formatting information.</param>
/// <returns>
/// An 32-bit unsigned integer equivalent to the value of this instance.
/// </returns>
uint IConvertible.ToUInt32( IFormatProvider provider )
{
return (uint)bytes;
}
/// <summary>
/// Converts the value of this instance to an equivalent 64-bit unsigned integer using the specified culture-specific formatting information.
/// </summary>
/// <param name="provider">An <see cref="T:IFormatProvider"></see> interface implementation that supplies culture-specific formatting information.</param>
/// <returns>
/// An 64-bit unsigned integer equivalent to the value of this instance.
/// </returns>
ulong IConvertible.ToUInt64( IFormatProvider provider )
{
return (ulong)bytes;
}
#endregion
#region IEquatable<DataSize> Members
/// <summary>
/// Indicates whether the current object is equal to another object of the same type.
/// </summary>
/// <param name="other">An object to compare with this object.</param>
/// <returns>
/// true if the current object is equal to the other parameter; otherwise, false.
/// </returns>
public bool Equals( DataSize other )
{
return bytes == other.bytes;
}
#endregion
#region IXmlSerializable Members
/// <summary>
/// This method is reserved and should not be used. When implementing the IXmlSerializable interface, you should return null (Nothing in Visual Basic) from this method, and instead, if specifying a custom schema is required, apply the <see cref="T:XmlSchemaProviderAttribute"/> to the class.
/// </summary>
/// <returns>
/// An <see cref="T:System.Xml.Schema.XmlSchema"/> that describes the XML representation of the object that is produced by the <see cref="M:IXmlSerializable.WriteXml"/> method and consumed by the <see cref="M:IXmlSerializable.ReadXml"/> method.
/// </returns>
System.Xml.Schema.XmlSchema IXmlSerializable.GetSchema( )
{
return null;
}
/// <summary>
/// Generates an object from its XML representation.
/// </summary>
/// <param name="reader">The <see cref="T:System.Xml.XmlReader"/> stream from which the object is deserialized.</param>
void IXmlSerializable.ReadXml( System.Xml.XmlReader reader )
{
this.bytes = reader.ReadElementContentAsLong( );
}
void IXmlSerializable.WriteXml( System.Xml.XmlWriter writer )
{
writer.WriteValue( this.bytes );
}
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment