Skip to content

Latest commit

 

History

History
154 lines (144 loc) · 4.52 KB

vi.b.2-using-value-types.md

File metadata and controls

154 lines (144 loc) · 4.52 KB

VI.B.2 Using value types

The following program shows how rational numbers can be implemented using value types.

[Example:

.assembly extern mscorlib { }
.assembly rational.exe { }
.class private sealed Rational extends [mscorlib]System.ValueType
         implements mscorlib]System.IComparable
{ .field public int32 Numerator
  .field public int32 Denominator

  .method virtual public int32 CompareTo(object o)
  // Implements IComparable::CompareTo(Object)
  { ldarg.0
    // 'this' as a managed pointer
    ldfld int32 value class Rational::Numerator
    ldarg.1     // 'o' as an object
    unbox value class Rational
    ldfld int32 value class Rational::Numerator
    beq.s TryDenom
    ldc.i4.0
    ret

TryDenom:
    ldarg.0     // 'this' as a managed pointer
    ldfld int32 value class Rational::Denominator
    ldarg.1     // 'o' as an object
    unbox value class Rational
    ldfld int32 class Rational::Denominator
    ceq
    ret
  }

  .method virtual public string ToString()
  // Implements Object::ToString
  { .locals init (class [mscorlib]System.Text.StringBuilder SB,
                  string S, object N, object D)
    newobj void [mscorlib]System.Text.StringBuilder::.ctor()
    stloc.s SB
    ldstr "The value is: {0}/{1}"
    stloc.s S
    ldarg.0     // Managed pointer to self
    dup
    ldfld int32 value class Rational::Numerator
    box [mscorlib]System.Int32
    stloc.s N
    ldfld int32 value class Rational::Denominator
    box [mscorlib]System.Int32
    stloc.s D
    ldloc.s SB
    ldloc.s S
    ldloc.s N
    ldloc.s D
    call instance class [mscorlib]System.Text.StringBuilder
      [mscorlib]System.Text.StringBuilder::AppendFormat(string,
        object, object)
    callvirt instance string [mscorlib]System.Object::ToString()
    ret
  }

  .method public value class Rational Mul(value class Rational)
  {
    .locals init (value class Rational Result)
    ldloca.s Result
    dup
    ldarg.0     // 'this'
    ldfld int32 value class Rational::Numerator
    ldarga.s    1     // arg
    ldfld int32 value class Rational::Numerator
    mul
    stfld int32 value class Rational::Numerator
    ldarg.0     // this
    ldfld int32 value class Rational::Denominator
    ldarga.s    1     // arg
    ldfld int32 value class Rational::Denominator
    mul
    stfld int32 value class Rational::Denominator
    ldloc.s Result
    ret
  }
}

.method static void main()
{
  .entrypoint
  .locals init (value class Rational Half,
                value class Rational Third,
                value class Rational Temporary,
                object H, object T)

  // Initialize Half, Third, H, and T
  ldloca.s Half
  dup
  ldc.i4.1
  stfld int32 value class Rational::Numerator
  ldc.i4.2
  stfld  int32 value class Rational::Denominator
  ldloca.s Third
  dup
  ldc.i4.1
  stfld int32 value class Rational::Numerator
  ldc.i4.3
  stfld int32 value class Rational::Denominator
  ldloc.s Half
  box value class Rational
  stloc.s H
  ldloc.s Third
  box value class Rational
  stloc.s T
  // WriteLine(H.IComparable::CompareTo(H))
  // Call CompareTo via interface using boxed instance
  ldloc H
  dup
  callvirt int32 [mscorlib]System.IComparable::CompareTo(object)
  call void [mscorlib]System.Console::WriteLine(bool)
  // WriteLine(Half.CompareTo(T))
  // Call CompareTo via value type directly
  ldloca.s Half
  ldloc T
  call instance int32
  value class Rational::CompareTo(object)
  call void [mscorlib]System.Console::WriteLine(bool)
  // WriteLine(Half.ToString())
  // Call virtual method via value type directly
  ldloca.s Half
  call instance string class Rational::ToString()
  call void [mscorlib]System.Console::WriteLine(string)
  // WriteLine(T.ToString)
  // Call virtual method inherited from Object, via boxed instance
  ldloc T
  callvirt string [mscorlib]System.Object::ToString()
  call void [mscorlib]System.Console::WriteLine(string)
  // WriteLine((Half.Mul(T)).ToString())
  // Mul is called on two value types, returning a value type
  // ToString is then called directly on that value type
  // Note that we are required to introduce a temporary variable
  //   since the call to ToString requires
  //   a managed pointer (address)
  ldloca.s Half
  ldloc.s Third
  call instance value class Rational
         Rational::Mul(value class Rational)
  stloc.s Temporary
  ldloca.s Temporary
  call instance string Rational::ToString()
  call void [mscorlib]System.Console::WriteLine(string)
  ret
}

end example]