I don’t know about you but I am sick and tired of the choice I have to make between pretty formatting of values and usability. This applies to pretty much all .NET technology and I assume most languages in general. What’s my problem? Well let’s say you list the size of all files by extension in a directory.
Dir . -Recurse |
Group Extension | %{
$_ |
Select Name,@{
N='Size';
E={($_.Group | Measure-Object Length -Sum).Sum }
}
}
The nice thing is, you can pipe this out to Sort-Object to sort by length. The downside is, it looks like crap. It would be nice if it showed MB, KB, bytes, etc. But once you format as a string, you can no longer easily filter or sort the output.
So please, reap the benefits of my frustration and use the following C# class with Add-Type to cast your data size formatting problems into oblivion.
Add-Type -ReferencedAssemblies System.Xml -TypeDefinition @"
... the code that stupid Windows Live says is too long to post ...
"@
Dir . -Recurse |
Group Extension | %{
$_ |
Select Name,@{
N='Size';
E={[DataSize]($_.Group | Measure-Object Length -Sum).Sum }
}
}
Source is below.
using System;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Xml.Serialization;
namespace Einstein
{
/// <summary>
/// Represents a file size or other data size in bytes, kilobytes, megabytes, etc.
/// </summary>
[Serializable]
[ImmutableObject( true )]
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 = 1;
/// <summary>
/// The size of a kilobyte, in bytes. This structure defines a KB as 1,024 bytes.
/// </summary>
public const long KilobyteSize = 1024;
/// <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 = 1048576;
/// <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 = 1073741824;
/// <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 = 1099511627776;
/// <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.Compiled | 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( );
} // if
else {
if ( requireUnit ) {
return false;
} // if
else {
numberPart = input;
unitPart = "B";
} // else
} // else
// 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.AllowDecimalPoint | NumberStyles.AllowLeadingSign | NumberStyles.AllowThousands, null, out number ) ) {
#region B.A.S.S. - Big Ass Switch Statement
switch ( unitPart.ToUpperInvariant( ) ) {
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;
} // switch
#endregion
dataSize = new DataSize( (long)number );
return true;
} // if
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:System.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:System.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:DataSize.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:System.String"></see> specifying the format to use.-or- null to use the default format defined for the type of the <see cref="T:System.IFormattable"></see> implementation.</param>
/// <param name="formatProvider">The <see cref="T:System.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:System.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." );
} // if
else {
throw new FormatException( "Invalid format specifier." );
} // else
} // if
else {
precision = 2;
} // else
switch ( formatMatch.Groups["unit"].Value.ToUpperInvariant( ) ) {
case "A":
// Automatic based on the size of the value
if ( Math.Truncate( Math.Abs( TotalTerabytes ) ) >= 1 )
goto case "T";
else if ( Math.Truncate( Math.Abs( TotalGigabytes ) ) >= 1 )
goto case "G";
else if ( Math.Truncate( Math.Abs( TotalMegabytes ) ) >= 1 )
goto case "M";
else if ( Math.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." );
} // switch
if ( formatMatch.Groups["nosuffix"].Success ) {
// They want the value without the suffix
return String.Format( formatProvider, "{0:N" + precision + "}", value );
} // if
else {
// They want the value with the sufffix
return String.Format( formatProvider, "{0:N" + precision + "} {1}", value, suffix );
} // else
} // if
else {
throw new FormatException( "Invalid format specifier." );
} // else
}
#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:System.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:System.TypeCode"></see> for this instance.
/// </summary>
/// <returns>
/// The enumerated constant that is the <see cref="T:System.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:System.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:System.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:System.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:System.DateTime"></see> using the specified culture-specific formatting information.
/// </summary>
/// <param name="provider">An <see cref="T:System.IFormatProvider"></see> interface implementation that supplies culture-specific formatting information.</param>
/// <returns>
/// A <see cref="T:System.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:System.Decimal"></see> number using the specified culture-specific formatting information.
/// </summary>
/// <param name="provider">An <see cref="T:System.IFormatProvider"></see> interface implementation that supplies culture-specific formatting information.</param>
/// <returns>
/// A <see cref="T:System.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:System.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:System.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:System.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:System.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:System.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:System.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:System.String"></see> using the specified culture-specific formatting information.
/// </summary>
/// <param name="provider">An <see cref="T:System.IFormatProvider"></see> interface implementation that supplies culture-specific formatting information.</param>
/// <returns>
/// A <see cref="T:System.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:System.Object"></see> of the specified <see cref="T:System.Type"></see> that has an equivalent value, using the specified culture-specific formatting information.
/// </summary>
/// <param name="conversionType">The <see cref="T:System.Type"></see> to which the value of this instance is converted.</param>
/// <param name="provider">An <see cref="T:System.IFormatProvider"></see> interface implementation that supplies culture-specific formatting information.</param>
/// <returns>
/// An <see cref="T:System.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 );
else if ( conversionType == typeof( DataSize ) )
return this;
else if ( conversionType == typeof( uint ) )
return convertible.ToUInt32( provider );
else if ( conversionType == typeof( int ) )
return convertible.ToInt32( provider );
else if ( conversionType == typeof( ulong ) )
return convertible.ToUInt64( provider );
else if ( conversionType == typeof( long ) )
return convertible.ToInt64( provider );
else if ( conversionType == typeof( float ) )
return convertible.ToSingle( provider );
else if ( conversionType == typeof( double ) )
return convertible.ToDouble( provider );
else if ( conversionType == typeof( decimal ) )
return convertible.ToDecimal( provider );
else if ( conversionType == typeof( byte ) )
return convertible.ToByte( provider );
else if ( conversionType == typeof( sbyte ) )
return convertible.ToSByte( provider );
else if ( conversionType == typeof( ushort ) )
return convertible.ToUInt16( provider );
else if ( conversionType == typeof( short ) )
return convertible.ToInt16( provider );
else if ( conversionType == typeof( bool ) )
return convertible.ToBoolean( provider );
else if ( conversionType == typeof( DateTime ) )
return convertible.ToDateTime( provider );
else if ( conversionType == typeof( char ) )
return convertible.ToChar( provider );
else
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:System.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:System.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:System.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:System.Xml.Serialization.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:System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter)"/> method and consumed by the <see cref="M:System.Xml.Serialization.IXmlSerializable.ReadXml(System.Xml.XmlReader)"/> 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
} // class
} // namespace