C# Without the Noise
I've been toying around with the idea on removing (what I perceive) as clutter and noise from C#.
Happened looking at the Money Type for the CLR project and thought it would be good example to see what affect it had.
Original
The Decluttering Begins
Conclusions
The Good:
In terms of line count it about a third of the size
I like the clean look.
The Bad: Under the current version properties aren't
Possible fix is to introduce a new Properties modifier
I've been toying around with the idea on removing (what I perceive) as clutter and noise from C#.
Happened looking at the Money Type for the CLR project and thought it would be good example to see what affect it had.
Original
using System;
namespace System
{
public struct Money : IEquatable<Money>,
IComparable<Money>,
IFormattable,
IConvertible
{
public static implicit operator Money(Byte value)
{ return new Money((Decimal)value); }
public static implicit operator Money(SByte value)
{ return new Money((Decimal)value); }
public static implicit operator Money(Single value)
{ return new Money((Decimal)value); }
public static implicit operator Money(Double value)
{ return new Money((Decimal)value); }
public static implicit operator Money(Decimal value)
{ return new Money(value); }
public static implicit operator Decimal(Money value)
{
return value.computeValue();
}
public static implicit operator Money(Int16 value)
{
return new Money((Decimal)value);
}
public static implicit operator Money(Int32 value)
{
return new Money((Decimal)value);
}
public static implicit operator Money(Int64 value)
{
return new Money((Decimal)value);
}
public static implicit operator Money(UInt16 value)
{
return new Money((Decimal)value);
}
public static implicit operator Money(UInt32 value)
{
return new Money((Decimal)value);
}
public static implicit operator Money(UInt64 value)
{
return new Money((Decimal)value);
}
public static Money operator -(Money value)
{
return new Money(-value._units, -value._decimalFraction, value._currency);
}
public static Money operator +(Money left, Money right)
{
if (left.Currency != right.Currency) throw differentCurrencies();
Int32 fractionSum = left._decimalFraction + right._decimalFraction;
Int64 overflow = 0;
Int32 fractionSign = Math.Sign(fractionSum);
Int32 absFractionSum = Math.Abs(fractionSum);
if (absFractionSum >= FractionScale)
{ overflow = fractionSign;
absFractionSum -= (Int32)FractionScale;
fractionSum = fractionSign * absFractionSum;
}
Int64 newUnits = left._units + right._units + overflow;
if (fractionSign < 0 && Math.Sign(newUnits) > 0)
{
newUnits -= 1;
fractionSum = (Int32)FractionScale - absFractionSum;
}
return new Money(newUnits, fractionSum, left.Currency);
}
public static Money operator -(Money left, Money right)
{
if (left.Currency != right.Currency) throw differentCurrencies();
return left + -right;
}
public static Money operator *(Money left, Decimal right)
{
return ((Decimal)left * right);
}
public static Money operator /(Money left, Decimal right)
{
return ((Decimal)left / right);
}
public static Boolean operator ==(Money left, Money right)
{
return left.Equals(right);
}
public static Boolean operator !=(Money left, Money right)
{
return !left.Equals(right);
}
public static Boolean operator >(Money left, Money right)
{
return left.CompareTo(right) > 0;
}
public static Boolean operator <(Money left, Money right)
{
return left.CompareTo(right) < 0;
}
public static Boolean operator >=(Money left, Money right)
{
return left.CompareTo(right) >= 0;
}
public static Boolean operator <=(Money left, Money right)
{
return left.CompareTo(right) <= 0;
}
private const Decimal FractionScale = 1E9M;
private readonly Currency _currency;
private readonly Int64 _units;
private readonly Int32 _decimalFraction;
public Money(Decimal value)
{
checkValue(value);
_units = (Int64)value;
_decimalFraction = (Int32)Decimal.Round((value - _units) * FractionScale);
if (_decimalFraction >= FractionScale)
{
_units += 1;
_decimalFraction = _decimalFraction - (Int32)FractionScale;
}
_currency = Currency.FromCurrentCulture();
}
public Money(Decimal value, Currency currency) : this(value)
{
_currency = currency;
}
private Money(Int64 units, Int32 fraction, Currency currency)
{
_units = units;
_decimalFraction = fraction;
_currency = currency;
}
public override Int32 GetHashCode()
{
return 207501131 ^ _units.GetHashCode() ^ _currency.GetHashCode();
}
public override Boolean Equals(Object obj)
{
if (!(obj is Money))
{
return false;
}
Money other = (Money)obj;
return Equals(other);
}
public override String ToString()
{
return computeValue().ToString("C");
}
public String ToString(String format)
{
return computeValue().ToString(format);
}
public Currency Currency
{
get { return _currency; }
}
#region Implementation of IEquatable<Money>
public Boolean Equals(Money other)
{
checkCurrencies(other);
return _units == other._units &&
_decimalFraction == other._decimalFraction;
}
#endregion
#region Implementation of IComparable<Money>
public Int32 CompareTo(Money other)
{
checkCurrencies(other);
Int32 unitCompare = _units.CompareTo(other._units);
return unitCompare == 0
? _decimalFraction.CompareTo(other._decimalFraction)
: unitCompare;
}
#endregion
#region Implementation of IFormattable
public String ToString(String format, IFormatProvider formatProvider)
{
return computeValue().ToString(format, formatProvider);
}
#endregion
#region Implementation of IConvertible
public TypeCode GetTypeCode()
{
return TypeCode.Object;
}
public Boolean ToBoolean(IFormatProvider provider)
{
return _units == 0 && _decimalFraction == 0;
}
public Char ToChar(IFormatProvider provider)
{
throw new NotSupportedException();
}
public SByte ToSByte(IFormatProvider provider)
{
return (SByte)computeValue();
}
public Byte ToByte(IFormatProvider provider)
{
return (Byte)computeValue();
}
public Int16 ToInt16(IFormatProvider provider)
{
return (Int16)computeValue();
}
public UInt16 ToUInt16(IFormatProvider provider)
{
return (UInt16)computeValue();
}
public Int32 ToInt32(IFormatProvider provider)
{
return (Int32)computeValue();
}
public UInt32 ToUInt32(IFormatProvider provider)
{
return (UInt32)computeValue();
}
public Int64 ToInt64(IFormatProvider provider)
{
return (Int64)computeValue();
}
public UInt64 ToUInt64(IFormatProvider provider)
{
return (UInt64)computeValue();
}
public Single ToSingle(IFormatProvider provider)
{
return (Single)computeValue();
}
public Double ToDouble(IFormatProvider provider)
{
return (Double)computeValue();
}
public Decimal ToDecimal(IFormatProvider provider)
{
return computeValue();
}
public DateTime ToDateTime(IFormatProvider provider)
{
throw new NotSupportedException();
}
public String ToString(IFormatProvider provider)
{
return ((Decimal)this).ToString(provider);
}
public Object ToType(Type conversionType, IFormatProvider provider)
{
throw new NotSupportedException();
}
#endregion
private Decimal computeValue()
{
return _units + _decimalFraction / FractionScale;
}
private static Exception differentCurrencies()
{
return new InvalidOperationException("Money values are in different " +
"currencies. Convert to the same " +
"currency before performing " +
"operations on the values.");
}
private static void checkValue(Decimal value)
{
if (value < Int64.MinValue || value > Int64.MaxValue)
{
throw new ArgumentOutOfRangeException("value",
value,
"Money value must be between " +
Int64.MinValue + " and " +
Int64.MaxValue);
}
}
private void checkCurrencies(Money other)
{
if (other.Currency != Currency)
{
throw differentCurrencies();
}
}
}
}
The Decluttering Begins
- General Appearence
- What if C# was line-orientated? So the semi-colon ; on the end of statement is no longer needed.
- Indentation is equivalent using { } or scoping, modifier and return type are inherited by descendant indentations.
- Code Folding will available at the start indentation to the end of the indentation.
Interfaces - <-- Interface is been implemented.
- return types on interface implementation are not needed, because they come from the template, and can't methods can not be differentiated on return type anyway.
Statically Check Interpolation - $@ Type-Safe and statically checked string interpolation, which means what ever is in braces is check to see if it is visible.
Copy-Cat Typing - (Money left right) Type from the previous is used for type of the next parameter. If the parameter is a different type the parameter must be preceeded by a comma before the type.
using System;
namespace System
public struct Money
Implements
IEquatable<Money>y
IComparable<Money>
IFormattable
IConvertible
private
static
Exception differentCurrencies() return new InvalidOperationException("Money values are in different currencies. Convert to the same currency before performing operations on the values.");
void checkValue(Decimal value)
if (value < Int64.MinValue || value > Int64.MaxValue)
throw new ArgumentOutOfRangeException("value", value, $@"Money value must be between ${Int64.MinValue} and ${Int64.MaxValue}")
Money
(Decimal value)
checkValue(value)
_units = (Int64)value
_decimalFraction = (Int32)Decimal.Round((value - _units) * FractionScale)
if (_decimalFraction >= FractionScale)
_units++
_decimalFraction = _decimalFraction - (Int32)FractionScale
_currency = Currency.FromCurrentCulture()
(Decimal value, Currency currency) : this(value) _currency = currency
(Int64 units, Int32 fraction, Currency currency)
_units = units
_decimalFraction = fraction
_currency = currency
const Decimal FractionScale = 1E9M
readonly
Currency _currency
Int64 _units
Int32 _decimalFraction
Decimal computeValue() return (_units + _decimalFraction) / FractionScale
void checkCurrencies(Money other) if (other.Currency != Currency) throw differentCurrencies()
public
override
Int32 GetHashCode() return 207501131 ^ _units.GetHashCode() ^ _currency.GetHashCode()
Boolean Equals(Object obj)
if (!(obj is Money)) return false
Money other = (Money)obj
return Equals(other)
String ToString() return computeValue().ToString("C")
String ToString(String format) return computeValue().ToString(format)
Currency Currency
get: return _currency
<-- IEquatable<Money>
Equals(Money other)
checkCurrencies(other)
return (_units == other._units) && (_decimalFraction == other._decimalFraction)
<-- IComparable<Money>
CompareTo(Money other)
checkCurrencies(other)
Int32 unitCompare = _units.CompareTo(other._units)
return unitCompare == 0 ? _decimalFraction.CompareTo(other._decimalFraction) : unitCompare
<-- IFormattable
ToString(String format, IFormatProvider formatProvider) return computeValue().ToString(format, formatProvider)
<-- ICovertable
GetTypeCode () return TypeCode.Object
ToBoolean (IFormatProvider provider) return (_units == 0) && (_decimalFraction == 0)
ToChar (IFormatProvider provider) throw new NotSupportedException()
ToSByte (IFormatProvider provider) return (SByte) computeValue()
ToByte (IFormatProvider provider) return (Byte) computeValue()
ToInt16 (IFormatProvider provider) return (Int16) computeValue()
ToUInt16 (IFormatProvider provider) return (UInt16) computeValue()
ToInt32 (IFormatProvider provider) return (Int32) computeValue()
ToUInt32 (IFormatProvider provider) return (UInt32) computeValue()
ToInt64 (IFormatProvider provider) return (Int64) computeValue()
ToUInt64 (IFormatProvider provider) return (UInt64) computeValue()
ToSingle (IFormatProvider provider) return (Single) computeValue()
ToDouble (IFormatProvider provider) return (Double) computeValue()
ToDecimal (IFormatProvider provider) return computeValue()
ToDateTime (IFormatProvider provider) throw new NotSupportedException()
ToString (IFormatProvider provider) return ((Decimal)this).ToString(provider)
ToType (Type conversionType, IFormatProvider provider) throw new NotSupportedException()
static
operator
implicit
Decimal(Money value) return value.computeValue()
Money
(Byte value) return new Money((Decimal)value)
(SByte value) return new Money((Decimal)value)
(Single value) return new Money((Decimal)value)
(Double value) return new Money((Decimal)value)
(Decimal value) return new Money(value)
(Int16 value) return new Money((Decimal)value)
(Int32 value) return new Money((Decimal)value)
(Int64 value) return new Money((Decimal)value)
(UInt16 value) return new Money((Decimal)value)
(UInt32 value) return new Money((Decimal)value)
(UInt64 value) return new Money((Decimal)value)
Money
- (Money value) return new Money(-value._units, -value._decimalFraction, value._currency)
+ (Money left right)
if (left.Currency != right.Currency) throw differentCurrencies()
Int32 fractionSum = left._decimalFraction + right._decimalFraction
Int64 overflow = 0;
Int32 fractionSign = Math.Sign(fractionSum)
Int32 absFractionSum = Math.Abs(fractionSum)
if (absFractionSum >= FractionScale)
overflow = fractionSign
absFractionSum -= (Int32)FractionScale
fractionSum = fractionSign * absFractionSum
Int64 newUnits = left._units + right._units + overflow
if (fractionSign < 0 && Math.Sign(newUnits) > 0)
newUnits -= 1
fractionSum = (Int32)FractionScale - absFractionSum
return new Money(newUnits, fractionSum, left.Currency)
- (Money left right)
if (left.Currency != right.Currency) throw differentCurrencies()
return left + -right
* (Money left, Decimal right) return ((Decimal)left * right)
/ (Money left, Decimal right) return ((Decimal)left / right)
Boolean
== (Money left right) return left.Equals(right)
!= (Money left right) return !left.Equals(right)
> (Money left right) return left.CompareTo(right) > 0
< (Money left right) return left.CompareTo(right) < 0
>= (Money left right) return left.CompareTo(right) >= 0
<= (Money left right) return left.CompareTo(right) <= 0
Conclusions
The Good:
In terms of line count it about a third of the size
I like the clean look.
The Bad: Under the current version properties aren't
String ToString(String format) return computeValue().ToString(format)
Currency Currency
get: return _currency
<-- IEquatable<Money>
Possible fix is to introduce a new Properties modifier
String ToString(String format) return computeValue().ToString(format)
Properties
Currency Currency
get: return _currency
<-- IEquatable<Money>
1 Comments On This Entry
Page 1 of 1
Braber01
16 April 2012 - 04:34 PM
You should check out the Boo.Net Extension it's kind of like this however it's mostly python syntax but I think you'll be happy with it
Page 1 of 1
|
|



1 Comments








|