anchor.diff:      }
   
   /// Provides an encoder implementation for a union of events
  -[<AbstractClass>]
  -type UnionContractEncoder<'Union, 'Format> internal () =
  +[<Sealed>]
  +type UnionContractEncoder<'Union, 'Format> internal 
  +    (shape : ShapeFSharpUnion<'Union>,
  +     labelIndex : BinSearch,
  +     caseEncoders : Func<'Union, EncodedUnion<'Format>>[],
  +     caseDecoders : Func<'Format, 'Union>[]) =
  +
       /// Gets the union case string identifier for given union instance
  -    abstract GetCaseName : value:'Union -> string
  +    member _.GetCaseName (value:'Union) : string =
  +        let tag = shape.GetTagByRef &value
  +        labelIndex.Values.[tag]
  +
       /// Encodes a union instance into a decoded representation
  -    abstract Encode      : value:'Union -> EncodedUnion<'Format>
  +    member _.Encode (value:'Union) : EncodedUnion<'Format> =
  +        let tag = shape.GetTagByRef &value
  +        caseEncoders.[tag].Invoke value
  +
       /// Decodes a formatted representation into a union instance. Can potentially throw FormatException
  -    abstract Decode      : encodedUnion:EncodedUnion<'Format> -> 'Union
  +    member _.Decode (encodedUnion:EncodedUnion<'Format>) : 'Union =
  +        let unrecognizedCaseName(caseName : string) =
  +            let msg = sprintf "Unrecognized case name '%O.%s'" typeof<'Union> caseName
  +            raise <| FormatException msg
  +
  +        match labelIndex.TryFindIndex encodedUnion.CaseName with
  +        |  -1 -> unrecognizedCaseName encodedUnion.CaseName
  +        | tag -> caseDecoders.[tag].Invoke encodedUnion.Payload
  +
       /// Decodes a formatted representation into a union instance. Does not throw exception on format mismatches
  -    abstract TryDecode   : encodedUnion:EncodedUnion<'Format> -> 'Union option
  +    member _.TryDecode (encodedUnion:EncodedUnion<'Format>) : 'Union option =
  +        match labelIndex.TryFindIndex encodedUnion.CaseName with
  +        |  -1 -> None
  +        | tag -> caseDecoders.[tag].Invoke encodedUnion.Payload |> Some
   
   [<AutoOpen>]
   module private Impl =
  
positive.code:                 | _ -> false
              | _ -> false
  
          let genUnionCaseEncoder (scase : ShapeFSharpUnionCase<'Union>) =
              // extract the case label identifier for given case
              let label =
                  scase.CaseInfo.GetCustomAttributes()
  
negative.code:                 |> Array.map (fun e -> e encoder)
                  |> Array.unzip
  
              new UnionContractEncoder<'Union, 'Format>(shape, labelIndex, caseEncoders, caseDecoders)
  
      type EncoderFactory<'Union, 'Format> private () =
          static let factory = lazy(mkUnionEncoder<'Union, 'Format>())
          static member Create requireRecordFields (e : IEncoder<_>) = factory.Value requireRecordFields e
  
  type UnionContractEncoder =
  
  