// Generated by ProtoGen, Version=2.3.0.277, Culture=neutral, PublicKeyToken=17b3b1f090c3ea48.  DO NOT EDIT!
#pragma warning disable 1591, 0612
#region Designer generated code

using pb = global::Google.ProtocolBuffers;
using pbc = global::Google.ProtocolBuffers.Collections;
using pbd = global::Google.ProtocolBuffers.Descriptors;
using scg = global::System.Collections.Generic;
namespace UnitTest.Issues.TestProtos {
  
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
  [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
  public static partial class UnitTestExtrasIssuesProtoFile {
  
    #region Extension registration
    public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {
    }
    #endregion
    #region Static variables
    internal static pbd::MessageDescriptor internal__static_unittest_issues_A__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.A, global::UnitTest.Issues.TestProtos.A.Builder> internal__static_unittest_issues_A__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_unittest_issues_B__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.B, global::UnitTest.Issues.TestProtos.B.Builder> internal__static_unittest_issues_B__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_unittest_issues_AB__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.AB, global::UnitTest.Issues.TestProtos.AB.Builder> internal__static_unittest_issues_AB__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_unittest_issues_NumberField__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.NumberField, global::UnitTest.Issues.TestProtos.NumberField.Builder> internal__static_unittest_issues_NumberField__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_unittest_issues_DeprecatedChild__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.DeprecatedChild, global::UnitTest.Issues.TestProtos.DeprecatedChild.Builder> internal__static_unittest_issues_DeprecatedChild__FieldAccessorTable;
    internal static pbd::MessageDescriptor internal__static_unittest_issues_DeprecatedFieldsMessage__Descriptor;
    internal static pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage, global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage.Builder> internal__static_unittest_issues_DeprecatedFieldsMessage__FieldAccessorTable;
    #endregion
    #region Descriptor
    public static pbd::FileDescriptor Descriptor {
      get { return descriptor; }
    }
    private static pbd::FileDescriptor descriptor;
    
    static UnitTestExtrasIssuesProtoFile() {
      byte[] descriptorData = global::System.Convert.FromBase64String(
          "ChxleHRlc3QvdW5pdHRlc3RfaXNzdWVzLnByb3RvEg91bml0dGVzdF9pc3N1" + 
          "ZXMaJGdvb2dsZS9wcm90b2J1Zi9jc2hhcnBfb3B0aW9ucy5wcm90byIPCgFB" + 
          "EgoKAl9BGAEgASgFIg8KAUISCgoCQl8YASABKAUiEQoCQUISCwoDYV9iGAEg" + 
          "ASgFIhoKC051bWJlckZpZWxkEgsKA18wMRgBIAEoBSIRCg9EZXByZWNhdGVk" + 
          "Q2hpbGQiuQIKF0RlcHJlY2F0ZWRGaWVsZHNNZXNzYWdlEhoKDlByaW1pdGl2" + 
          "ZVZhbHVlGAEgASgFQgIYARIaCg5QcmltaXRpdmVBcnJheRgCIAMoBUICGAES" + 
          "OgoMTWVzc2FnZVZhbHVlGAMgASgLMiAudW5pdHRlc3RfaXNzdWVzLkRlcHJl" + 
          "Y2F0ZWRDaGlsZEICGAESOgoMTWVzc2FnZUFycmF5GAQgAygLMiAudW5pdHRl" + 
          "c3RfaXNzdWVzLkRlcHJlY2F0ZWRDaGlsZEICGAESNgoJRW51bVZhbHVlGAUg" + 
          "ASgOMh8udW5pdHRlc3RfaXNzdWVzLkRlcHJlY2F0ZWRFbnVtQgIYARI2CglF" + 
          "bnVtQXJyYXkYBiADKA4yHy51bml0dGVzdF9pc3N1ZXMuRGVwcmVjYXRlZEVu" + 
          "dW1CAhgBKhkKDkRlcHJlY2F0ZWRFbnVtEgcKA29uZRABQkBIAcI+OwoaVW5p" + 
          "dFRlc3QuSXNzdWVzLlRlc3RQcm90b3MSHVVuaXRUZXN0RXh0cmFzSXNzdWVz" + 
          "UHJvdG9GaWxl");
      pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {
        descriptor = root;
        internal__static_unittest_issues_A__Descriptor = Descriptor.MessageTypes[0];
        internal__static_unittest_issues_A__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.A, global::UnitTest.Issues.TestProtos.A.Builder>(internal__static_unittest_issues_A__Descriptor,
                new string[] { "A_", });
        internal__static_unittest_issues_B__Descriptor = Descriptor.MessageTypes[1];
        internal__static_unittest_issues_B__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.B, global::UnitTest.Issues.TestProtos.B.Builder>(internal__static_unittest_issues_B__Descriptor,
                new string[] { "B_", });
        internal__static_unittest_issues_AB__Descriptor = Descriptor.MessageTypes[2];
        internal__static_unittest_issues_AB__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.AB, global::UnitTest.Issues.TestProtos.AB.Builder>(internal__static_unittest_issues_AB__Descriptor,
                new string[] { "AB_", });
        internal__static_unittest_issues_NumberField__Descriptor = Descriptor.MessageTypes[3];
        internal__static_unittest_issues_NumberField__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.NumberField, global::UnitTest.Issues.TestProtos.NumberField.Builder>(internal__static_unittest_issues_NumberField__Descriptor,
                new string[] { "_01", });
        internal__static_unittest_issues_DeprecatedChild__Descriptor = Descriptor.MessageTypes[4];
        internal__static_unittest_issues_DeprecatedChild__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.DeprecatedChild, global::UnitTest.Issues.TestProtos.DeprecatedChild.Builder>(internal__static_unittest_issues_DeprecatedChild__Descriptor,
                new string[] { });
        internal__static_unittest_issues_DeprecatedFieldsMessage__Descriptor = Descriptor.MessageTypes[5];
        internal__static_unittest_issues_DeprecatedFieldsMessage__FieldAccessorTable = 
            new pb::FieldAccess.FieldAccessorTable<global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage, global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage.Builder>(internal__static_unittest_issues_DeprecatedFieldsMessage__Descriptor,
                new string[] { "PrimitiveValue", "PrimitiveArray", "MessageValue", "MessageArray", "EnumValue", "EnumArray", });
        pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();
        RegisterAllExtensions(registry);
        global::Google.ProtocolBuffers.DescriptorProtos.CSharpOptions.RegisterAllExtensions(registry);
        return registry;
      };
      pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,
          new pbd::FileDescriptor[] {
          global::Google.ProtocolBuffers.DescriptorProtos.CSharpOptions.Descriptor, 
          }, assigner);
    }
    #endregion
    
  }
  #region Enums
  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
  [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
  public enum DeprecatedEnum {
    one = 1,
  }
  
  #endregion
  
  #region Messages
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
  [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
  public sealed partial class A : pb::GeneratedMessage<A, A.Builder> {
    private static readonly A defaultInstance = new Builder().BuildPartial();
    private static readonly string[] _aFieldNames = new string[] { "_A" };
    private static readonly uint[] _aFieldTags = new uint[] { 8 };
    public static A DefaultInstance {
      get { return defaultInstance; }
    }
    
    public override A DefaultInstanceForType {
      get { return defaultInstance; }
    }
    
    protected override A ThisMessage {
      get { return this; }
    }
    
    public static pbd::MessageDescriptor Descriptor {
      get { return global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.internal__static_unittest_issues_A__Descriptor; }
    }
    
    protected override pb::FieldAccess.FieldAccessorTable<A, A.Builder> InternalFieldAccessors {
      get { return global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.internal__static_unittest_issues_A__FieldAccessorTable; }
    }
    
    public const int A_FieldNumber = 1;
    private bool hasA_;
    private int a_;
    public bool HasA_ {
      get { return hasA_; }
    }
    public int A_ {
      get { return a_; }
    }
    
    public override bool IsInitialized {
      get {
        return true;
      }
    }
    
    public override void WriteTo(pb::ICodedOutputStream output) {
      int size = SerializedSize;
      string[] field_names = _aFieldNames;
      if (hasA_) {
        output.WriteInt32(1, field_names[0], A_);
      }
      UnknownFields.WriteTo(output);
    }
    
    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        
        size = 0;
        if (hasA_) {
          size += pb::CodedOutputStream.ComputeInt32Size(1, A_);
        }
        size += UnknownFields.SerializedSize;
        memoizedSerializedSize = size;
        return size;
      }
    }
    
    public static A ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static A ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static A ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static A ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static A ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static A ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static A ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static A ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static A ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static A ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(A prototype) {
      return (Builder) new Builder().MergeFrom(prototype);
    }
    
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
    public sealed partial class Builder : pb::GeneratedBuilder<A, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {}
      
      A result = new A();
      
      protected override A MessageBeingBuilt {
        get { return result; }
      }
      
      public override Builder Clear() {
        result = new A();
        return this;
      }
      
      public override Builder Clone() {
        return new Builder().MergeFrom(result);
      }
      
      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::UnitTest.Issues.TestProtos.A.Descriptor; }
      }
      
      public override A DefaultInstanceForType {
        get { return global::UnitTest.Issues.TestProtos.A.DefaultInstance; }
      }
      
      public override A BuildPartial() {
        if (result == null) {
          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
        }
        A returnMe = result;
        result = null;
        return returnMe;
      }
      
      public override Builder MergeFrom(pb::IMessage other) {
        if (other is A) {
          return MergeFrom((A) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }
      
      public override Builder MergeFrom(A other) {
        if (other == global::UnitTest.Issues.TestProtos.A.DefaultInstance) return this;
        if (other.HasA_) {
          A_ = other.A_;
        }
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }
      
      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }
      
      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_aFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _aFieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
            case 8: {
              result.hasA_ = input.ReadInt32(ref result.a_);
              break;
            }
          }
        }
        
        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }
      
      
      public bool HasA_ {
        get { return result.hasA_; }
      }
      public int A_ {
        get { return result.A_; }
        set { SetA_(value); }
      }
      public Builder SetA_(int value) {
        result.hasA_ = true;
        result.a_ = value;
        return this;
      }
      public Builder ClearA_() {
        result.hasA_ = false;
        result.a_ = 0;
        return this;
      }
    }
    static A() {
      object.ReferenceEquals(global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.Descriptor, null);
    }
  }
  
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
  [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
  public sealed partial class B : pb::GeneratedMessage<B, B.Builder> {
    private static readonly B defaultInstance = new Builder().BuildPartial();
    private static readonly string[] _bFieldNames = new string[] { "B_" };
    private static readonly uint[] _bFieldTags = new uint[] { 8 };
    public static B DefaultInstance {
      get { return defaultInstance; }
    }
    
    public override B DefaultInstanceForType {
      get { return defaultInstance; }
    }
    
    protected override B ThisMessage {
      get { return this; }
    }
    
    public static pbd::MessageDescriptor Descriptor {
      get { return global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.internal__static_unittest_issues_B__Descriptor; }
    }
    
    protected override pb::FieldAccess.FieldAccessorTable<B, B.Builder> InternalFieldAccessors {
      get { return global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.internal__static_unittest_issues_B__FieldAccessorTable; }
    }
    
    public const int B_FieldNumber = 1;
    private bool hasB_;
    private int b_;
    public bool HasB_ {
      get { return hasB_; }
    }
    public int B_ {
      get { return b_; }
    }
    
    public override bool IsInitialized {
      get {
        return true;
      }
    }
    
    public override void WriteTo(pb::ICodedOutputStream output) {
      int size = SerializedSize;
      string[] field_names = _bFieldNames;
      if (hasB_) {
        output.WriteInt32(1, field_names[0], B_);
      }
      UnknownFields.WriteTo(output);
    }
    
    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        
        size = 0;
        if (hasB_) {
          size += pb::CodedOutputStream.ComputeInt32Size(1, B_);
        }
        size += UnknownFields.SerializedSize;
        memoizedSerializedSize = size;
        return size;
      }
    }
    
    public static B ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static B ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static B ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static B ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static B ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static B ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static B ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static B ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static B ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static B ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(B prototype) {
      return (Builder) new Builder().MergeFrom(prototype);
    }
    
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
    public sealed partial class Builder : pb::GeneratedBuilder<B, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {}
      
      B result = new B();
      
      protected override B MessageBeingBuilt {
        get { return result; }
      }
      
      public override Builder Clear() {
        result = new B();
        return this;
      }
      
      public override Builder Clone() {
        return new Builder().MergeFrom(result);
      }
      
      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::UnitTest.Issues.TestProtos.B.Descriptor; }
      }
      
      public override B DefaultInstanceForType {
        get { return global::UnitTest.Issues.TestProtos.B.DefaultInstance; }
      }
      
      public override B BuildPartial() {
        if (result == null) {
          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
        }
        B returnMe = result;
        result = null;
        return returnMe;
      }
      
      public override Builder MergeFrom(pb::IMessage other) {
        if (other is B) {
          return MergeFrom((B) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }
      
      public override Builder MergeFrom(B other) {
        if (other == global::UnitTest.Issues.TestProtos.B.DefaultInstance) return this;
        if (other.HasB_) {
          B_ = other.B_;
        }
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }
      
      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }
      
      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_bFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _bFieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
            case 8: {
              result.hasB_ = input.ReadInt32(ref result.b_);
              break;
            }
          }
        }
        
        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }
      
      
      public bool HasB_ {
        get { return result.hasB_; }
      }
      public int B_ {
        get { return result.B_; }
        set { SetB_(value); }
      }
      public Builder SetB_(int value) {
        result.hasB_ = true;
        result.b_ = value;
        return this;
      }
      public Builder ClearB_() {
        result.hasB_ = false;
        result.b_ = 0;
        return this;
      }
    }
    static B() {
      object.ReferenceEquals(global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.Descriptor, null);
    }
  }
  
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
  [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
  public sealed partial class AB : pb::GeneratedMessage<AB, AB.Builder> {
    private static readonly AB defaultInstance = new Builder().BuildPartial();
    private static readonly string[] _aBFieldNames = new string[] { "a_b" };
    private static readonly uint[] _aBFieldTags = new uint[] { 8 };
    public static AB DefaultInstance {
      get { return defaultInstance; }
    }
    
    public override AB DefaultInstanceForType {
      get { return defaultInstance; }
    }
    
    protected override AB ThisMessage {
      get { return this; }
    }
    
    public static pbd::MessageDescriptor Descriptor {
      get { return global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.internal__static_unittest_issues_AB__Descriptor; }
    }
    
    protected override pb::FieldAccess.FieldAccessorTable<AB, AB.Builder> InternalFieldAccessors {
      get { return global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.internal__static_unittest_issues_AB__FieldAccessorTable; }
    }
    
    public const int AB_FieldNumber = 1;
    private bool hasAB_;
    private int aB_;
    public bool HasAB_ {
      get { return hasAB_; }
    }
    public int AB_ {
      get { return aB_; }
    }
    
    public override bool IsInitialized {
      get {
        return true;
      }
    }
    
    public override void WriteTo(pb::ICodedOutputStream output) {
      int size = SerializedSize;
      string[] field_names = _aBFieldNames;
      if (hasAB_) {
        output.WriteInt32(1, field_names[0], AB_);
      }
      UnknownFields.WriteTo(output);
    }
    
    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        
        size = 0;
        if (hasAB_) {
          size += pb::CodedOutputStream.ComputeInt32Size(1, AB_);
        }
        size += UnknownFields.SerializedSize;
        memoizedSerializedSize = size;
        return size;
      }
    }
    
    public static AB ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static AB ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static AB ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static AB ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static AB ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static AB ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static AB ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static AB ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static AB ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static AB ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(AB prototype) {
      return (Builder) new Builder().MergeFrom(prototype);
    }
    
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
    public sealed partial class Builder : pb::GeneratedBuilder<AB, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {}
      
      AB result = new AB();
      
      protected override AB MessageBeingBuilt {
        get { return result; }
      }
      
      public override Builder Clear() {
        result = new AB();
        return this;
      }
      
      public override Builder Clone() {
        return new Builder().MergeFrom(result);
      }
      
      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::UnitTest.Issues.TestProtos.AB.Descriptor; }
      }
      
      public override AB DefaultInstanceForType {
        get { return global::UnitTest.Issues.TestProtos.AB.DefaultInstance; }
      }
      
      public override AB BuildPartial() {
        if (result == null) {
          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
        }
        AB returnMe = result;
        result = null;
        return returnMe;
      }
      
      public override Builder MergeFrom(pb::IMessage other) {
        if (other is AB) {
          return MergeFrom((AB) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }
      
      public override Builder MergeFrom(AB other) {
        if (other == global::UnitTest.Issues.TestProtos.AB.DefaultInstance) return this;
        if (other.HasAB_) {
          AB_ = other.AB_;
        }
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }
      
      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }
      
      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_aBFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _aBFieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
            case 8: {
              result.hasAB_ = input.ReadInt32(ref result.aB_);
              break;
            }
          }
        }
        
        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }
      
      
      public bool HasAB_ {
        get { return result.hasAB_; }
      }
      public int AB_ {
        get { return result.AB_; }
        set { SetAB_(value); }
      }
      public Builder SetAB_(int value) {
        result.hasAB_ = true;
        result.aB_ = value;
        return this;
      }
      public Builder ClearAB_() {
        result.hasAB_ = false;
        result.aB_ = 0;
        return this;
      }
    }
    static AB() {
      object.ReferenceEquals(global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.Descriptor, null);
    }
  }
  
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
  [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
  public sealed partial class NumberField : pb::GeneratedMessage<NumberField, NumberField.Builder> {
    private static readonly NumberField defaultInstance = new Builder().BuildPartial();
    private static readonly string[] _numberFieldFieldNames = new string[] { "_01" };
    private static readonly uint[] _numberFieldFieldTags = new uint[] { 8 };
    public static NumberField DefaultInstance {
      get { return defaultInstance; }
    }
    
    public override NumberField DefaultInstanceForType {
      get { return defaultInstance; }
    }
    
    protected override NumberField ThisMessage {
      get { return this; }
    }
    
    public static pbd::MessageDescriptor Descriptor {
      get { return global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.internal__static_unittest_issues_NumberField__Descriptor; }
    }
    
    protected override pb::FieldAccess.FieldAccessorTable<NumberField, NumberField.Builder> InternalFieldAccessors {
      get { return global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.internal__static_unittest_issues_NumberField__FieldAccessorTable; }
    }
    
    [global::System.CLSCompliant(false)]
    public const int _01FieldNumber = 1;
    private bool has_01;
    private int _01_;
    public bool Has_01 {
      get { return has_01; }
    }
    [global::System.CLSCompliant(false)]
    public int _01 {
      get { return _01_; }
    }
    
    public override bool IsInitialized {
      get {
        return true;
      }
    }
    
    public override void WriteTo(pb::ICodedOutputStream output) {
      int size = SerializedSize;
      string[] field_names = _numberFieldFieldNames;
      if (has_01) {
        output.WriteInt32(1, field_names[0], _01);
      }
      UnknownFields.WriteTo(output);
    }
    
    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        
        size = 0;
        if (has_01) {
          size += pb::CodedOutputStream.ComputeInt32Size(1, _01);
        }
        size += UnknownFields.SerializedSize;
        memoizedSerializedSize = size;
        return size;
      }
    }
    
    public static NumberField ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static NumberField ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static NumberField ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static NumberField ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static NumberField ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static NumberField ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static NumberField ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static NumberField ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static NumberField ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static NumberField ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(NumberField prototype) {
      return (Builder) new Builder().MergeFrom(prototype);
    }
    
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
    public sealed partial class Builder : pb::GeneratedBuilder<NumberField, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {}
      
      NumberField result = new NumberField();
      
      protected override NumberField MessageBeingBuilt {
        get { return result; }
      }
      
      public override Builder Clear() {
        result = new NumberField();
        return this;
      }
      
      public override Builder Clone() {
        return new Builder().MergeFrom(result);
      }
      
      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::UnitTest.Issues.TestProtos.NumberField.Descriptor; }
      }
      
      public override NumberField DefaultInstanceForType {
        get { return global::UnitTest.Issues.TestProtos.NumberField.DefaultInstance; }
      }
      
      public override NumberField BuildPartial() {
        if (result == null) {
          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
        }
        NumberField returnMe = result;
        result = null;
        return returnMe;
      }
      
      public override Builder MergeFrom(pb::IMessage other) {
        if (other is NumberField) {
          return MergeFrom((NumberField) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }
      
      public override Builder MergeFrom(NumberField other) {
        if (other == global::UnitTest.Issues.TestProtos.NumberField.DefaultInstance) return this;
        if (other.Has_01) {
          _01 = other._01;
        }
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }
      
      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }
      
      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_numberFieldFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _numberFieldFieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
            case 8: {
              result.has_01 = input.ReadInt32(ref result._01_);
              break;
            }
          }
        }
        
        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }
      
      
      public bool Has_01 {
        get { return result.has_01; }
      }
      [global::System.CLSCompliant(false)]
      public int _01 {
        get { return result._01; }
        set { Set_01(value); }
      }
      [global::System.CLSCompliant(false)]
      public Builder Set_01(int value) {
        result.has_01 = true;
        result._01_ = value;
        return this;
      }
      public Builder Clear_01() {
        result.has_01 = false;
        result._01_ = 0;
        return this;
      }
    }
    static NumberField() {
      object.ReferenceEquals(global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.Descriptor, null);
    }
  }
  
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
  [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
  public sealed partial class DeprecatedChild : pb::GeneratedMessage<DeprecatedChild, DeprecatedChild.Builder> {
    private static readonly DeprecatedChild defaultInstance = new Builder().BuildPartial();
    private static readonly string[] _deprecatedChildFieldNames = new string[] {  };
    private static readonly uint[] _deprecatedChildFieldTags = new uint[] {  };
    public static DeprecatedChild DefaultInstance {
      get { return defaultInstance; }
    }
    
    public override DeprecatedChild DefaultInstanceForType {
      get { return defaultInstance; }
    }
    
    protected override DeprecatedChild ThisMessage {
      get { return this; }
    }
    
    public static pbd::MessageDescriptor Descriptor {
      get { return global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.internal__static_unittest_issues_DeprecatedChild__Descriptor; }
    }
    
    protected override pb::FieldAccess.FieldAccessorTable<DeprecatedChild, DeprecatedChild.Builder> InternalFieldAccessors {
      get { return global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.internal__static_unittest_issues_DeprecatedChild__FieldAccessorTable; }
    }
    
    public override bool IsInitialized {
      get {
        return true;
      }
    }
    
    public override void WriteTo(pb::ICodedOutputStream output) {
      int size = SerializedSize;
      string[] field_names = _deprecatedChildFieldNames;
      UnknownFields.WriteTo(output);
    }
    
    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        
        size = 0;
        size += UnknownFields.SerializedSize;
        memoizedSerializedSize = size;
        return size;
      }
    }
    
    public static DeprecatedChild ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static DeprecatedChild ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static DeprecatedChild ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static DeprecatedChild ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static DeprecatedChild ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static DeprecatedChild ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static DeprecatedChild ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static DeprecatedChild ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static DeprecatedChild ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static DeprecatedChild ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(DeprecatedChild prototype) {
      return (Builder) new Builder().MergeFrom(prototype);
    }
    
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
    public sealed partial class Builder : pb::GeneratedBuilder<DeprecatedChild, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {}
      
      DeprecatedChild result = new DeprecatedChild();
      
      protected override DeprecatedChild MessageBeingBuilt {
        get { return result; }
      }
      
      public override Builder Clear() {
        result = new DeprecatedChild();
        return this;
      }
      
      public override Builder Clone() {
        return new Builder().MergeFrom(result);
      }
      
      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::UnitTest.Issues.TestProtos.DeprecatedChild.Descriptor; }
      }
      
      public override DeprecatedChild DefaultInstanceForType {
        get { return global::UnitTest.Issues.TestProtos.DeprecatedChild.DefaultInstance; }
      }
      
      public override DeprecatedChild BuildPartial() {
        if (result == null) {
          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
        }
        DeprecatedChild returnMe = result;
        result = null;
        return returnMe;
      }
      
      public override Builder MergeFrom(pb::IMessage other) {
        if (other is DeprecatedChild) {
          return MergeFrom((DeprecatedChild) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }
      
      public override Builder MergeFrom(DeprecatedChild other) {
        if (other == global::UnitTest.Issues.TestProtos.DeprecatedChild.DefaultInstance) return this;
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }
      
      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }
      
      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_deprecatedChildFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _deprecatedChildFieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
          }
        }
        
        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }
      
    }
    static DeprecatedChild() {
      object.ReferenceEquals(global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.Descriptor, null);
    }
  }
  
  [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
  [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
  [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
  public sealed partial class DeprecatedFieldsMessage : pb::GeneratedMessage<DeprecatedFieldsMessage, DeprecatedFieldsMessage.Builder> {
    private static readonly DeprecatedFieldsMessage defaultInstance = new Builder().BuildPartial();
    private static readonly string[] _deprecatedFieldsMessageFieldNames = new string[] { "EnumArray", "EnumValue", "MessageArray", "MessageValue", "PrimitiveArray", "PrimitiveValue" };
    private static readonly uint[] _deprecatedFieldsMessageFieldTags = new uint[] { 48, 40, 34, 26, 16, 8 };
    public static DeprecatedFieldsMessage DefaultInstance {
      get { return defaultInstance; }
    }
    
    public override DeprecatedFieldsMessage DefaultInstanceForType {
      get { return defaultInstance; }
    }
    
    protected override DeprecatedFieldsMessage ThisMessage {
      get { return this; }
    }
    
    public static pbd::MessageDescriptor Descriptor {
      get { return global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.internal__static_unittest_issues_DeprecatedFieldsMessage__Descriptor; }
    }
    
    protected override pb::FieldAccess.FieldAccessorTable<DeprecatedFieldsMessage, DeprecatedFieldsMessage.Builder> InternalFieldAccessors {
      get { return global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.internal__static_unittest_issues_DeprecatedFieldsMessage__FieldAccessorTable; }
    }
    
    public const int PrimitiveValueFieldNumber = 1;
    private bool hasPrimitiveValue;
    private int primitiveValue_;
    [global::System.ObsoleteAttribute()]
    public bool HasPrimitiveValue {
      get { return hasPrimitiveValue; }
    }
    [global::System.ObsoleteAttribute()]
    public int PrimitiveValue {
      get { return primitiveValue_; }
    }
    
    public const int PrimitiveArrayFieldNumber = 2;
    private pbc::PopsicleList<int> primitiveArray_ = new pbc::PopsicleList<int>();
    [global::System.ObsoleteAttribute()]
    public scg::IList<int> PrimitiveArrayList {
      get { return pbc::Lists.AsReadOnly(primitiveArray_); }
    }
    [global::System.ObsoleteAttribute()]
    public int PrimitiveArrayCount {
      get { return primitiveArray_.Count; }
    }
    [global::System.ObsoleteAttribute()]
    public int GetPrimitiveArray(int index) {
      return primitiveArray_[index];
    }
    
    public const int MessageValueFieldNumber = 3;
    private bool hasMessageValue;
    private global::UnitTest.Issues.TestProtos.DeprecatedChild messageValue_ = global::UnitTest.Issues.TestProtos.DeprecatedChild.DefaultInstance;
    [global::System.ObsoleteAttribute()]
    public bool HasMessageValue {
      get { return hasMessageValue; }
    }
    [global::System.ObsoleteAttribute()]
    public global::UnitTest.Issues.TestProtos.DeprecatedChild MessageValue {
      get { return messageValue_; }
    }
    
    public const int MessageArrayFieldNumber = 4;
    private pbc::PopsicleList<global::UnitTest.Issues.TestProtos.DeprecatedChild> messageArray_ = new pbc::PopsicleList<global::UnitTest.Issues.TestProtos.DeprecatedChild>();
    [global::System.ObsoleteAttribute()]
    public scg::IList<global::UnitTest.Issues.TestProtos.DeprecatedChild> MessageArrayList {
      get { return messageArray_; }
    }
    [global::System.ObsoleteAttribute()]
    public int MessageArrayCount {
      get { return messageArray_.Count; }
    }
    [global::System.ObsoleteAttribute()]
    public global::UnitTest.Issues.TestProtos.DeprecatedChild GetMessageArray(int index) {
      return messageArray_[index];
    }
    
    public const int EnumValueFieldNumber = 5;
    private bool hasEnumValue;
    private global::UnitTest.Issues.TestProtos.DeprecatedEnum enumValue_ = global::UnitTest.Issues.TestProtos.DeprecatedEnum.one;
    [global::System.ObsoleteAttribute()]
    public bool HasEnumValue {
      get { return hasEnumValue; }
    }
    [global::System.ObsoleteAttribute()]
    public global::UnitTest.Issues.TestProtos.DeprecatedEnum EnumValue {
      get { return enumValue_; }
    }
    
    public const int EnumArrayFieldNumber = 6;
    private pbc::PopsicleList<global::UnitTest.Issues.TestProtos.DeprecatedEnum> enumArray_ = new pbc::PopsicleList<global::UnitTest.Issues.TestProtos.DeprecatedEnum>();
    [global::System.ObsoleteAttribute()]
    public scg::IList<global::UnitTest.Issues.TestProtos.DeprecatedEnum> EnumArrayList {
      get { return pbc::Lists.AsReadOnly(enumArray_); }
    }
    [global::System.ObsoleteAttribute()]
    public int EnumArrayCount {
      get { return enumArray_.Count; }
    }
    [global::System.ObsoleteAttribute()]
    public global::UnitTest.Issues.TestProtos.DeprecatedEnum GetEnumArray(int index) {
      return enumArray_[index];
    }
    
    public override bool IsInitialized {
      get {
        return true;
      }
    }
    
    public override void WriteTo(pb::ICodedOutputStream output) {
      int size = SerializedSize;
      string[] field_names = _deprecatedFieldsMessageFieldNames;
      if (hasPrimitiveValue) {
        output.WriteInt32(1, field_names[5], PrimitiveValue);
      }
      if (primitiveArray_.Count > 0) {
        output.WriteInt32Array(2, field_names[4], primitiveArray_);
      }
      if (hasMessageValue) {
        output.WriteMessage(3, field_names[3], MessageValue);
      }
      if (messageArray_.Count > 0) {
        output.WriteMessageArray(4, field_names[2], messageArray_);
      }
      if (hasEnumValue) {
        output.WriteEnum(5, field_names[1], (int) EnumValue, EnumValue);
      }
      if (enumArray_.Count > 0) {
        output.WriteEnumArray(6, field_names[0], enumArray_);
      }
      UnknownFields.WriteTo(output);
    }
    
    private int memoizedSerializedSize = -1;
    public override int SerializedSize {
      get {
        int size = memoizedSerializedSize;
        if (size != -1) return size;
        
        size = 0;
        if (hasPrimitiveValue) {
          size += pb::CodedOutputStream.ComputeInt32Size(1, PrimitiveValue);
        }
        {
          int dataSize = 0;
          foreach (int element in PrimitiveArrayList) {
            dataSize += pb::CodedOutputStream.ComputeInt32SizeNoTag(element);
          }
          size += dataSize;
          size += 1 * primitiveArray_.Count;
        }
        if (hasMessageValue) {
          size += pb::CodedOutputStream.ComputeMessageSize(3, MessageValue);
        }
        foreach (global::UnitTest.Issues.TestProtos.DeprecatedChild element in MessageArrayList) {
          size += pb::CodedOutputStream.ComputeMessageSize(4, element);
        }
        if (hasEnumValue) {
          size += pb::CodedOutputStream.ComputeEnumSize(5, (int) EnumValue);
        }
        {
          int dataSize = 0;
          if (enumArray_.Count > 0) {
            foreach (global::UnitTest.Issues.TestProtos.DeprecatedEnum element in enumArray_) {
              dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element);
            }
            size += dataSize;
            size += 1 * enumArray_.Count;
          }
        }
        size += UnknownFields.SerializedSize;
        memoizedSerializedSize = size;
        return size;
      }
    }
    
    public static DeprecatedFieldsMessage ParseFrom(pb::ByteString data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static DeprecatedFieldsMessage ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static DeprecatedFieldsMessage ParseFrom(byte[] data) {
      return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();
    }
    public static DeprecatedFieldsMessage ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();
    }
    public static DeprecatedFieldsMessage ParseFrom(global::System.IO.Stream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static DeprecatedFieldsMessage ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static DeprecatedFieldsMessage ParseDelimitedFrom(global::System.IO.Stream input) {
      return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();
    }
    public static DeprecatedFieldsMessage ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {
      return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();
    }
    public static DeprecatedFieldsMessage ParseFrom(pb::ICodedInputStream input) {
      return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();
    }
    public static DeprecatedFieldsMessage ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
      return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();
    }
    public static Builder CreateBuilder() { return new Builder(); }
    public override Builder ToBuilder() { return CreateBuilder(this); }
    public override Builder CreateBuilderForType() { return new Builder(); }
    public static Builder CreateBuilder(DeprecatedFieldsMessage prototype) {
      return (Builder) new Builder().MergeFrom(prototype);
    }
    
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("ProtoGen", "2.3.0.277")]
    public sealed partial class Builder : pb::GeneratedBuilder<DeprecatedFieldsMessage, Builder> {
      protected override Builder ThisBuilder {
        get { return this; }
      }
      public Builder() {}
      
      DeprecatedFieldsMessage result = new DeprecatedFieldsMessage();
      
      protected override DeprecatedFieldsMessage MessageBeingBuilt {
        get { return result; }
      }
      
      public override Builder Clear() {
        result = new DeprecatedFieldsMessage();
        return this;
      }
      
      public override Builder Clone() {
        return new Builder().MergeFrom(result);
      }
      
      public override pbd::MessageDescriptor DescriptorForType {
        get { return global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage.Descriptor; }
      }
      
      public override DeprecatedFieldsMessage DefaultInstanceForType {
        get { return global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage.DefaultInstance; }
      }
      
      public override DeprecatedFieldsMessage BuildPartial() {
        if (result == null) {
          throw new global::System.InvalidOperationException("build() has already been called on this Builder");
        }
        result.primitiveArray_.MakeReadOnly();
        result.messageArray_.MakeReadOnly();
        result.enumArray_.MakeReadOnly();
        DeprecatedFieldsMessage returnMe = result;
        result = null;
        return returnMe;
      }
      
      public override Builder MergeFrom(pb::IMessage other) {
        if (other is DeprecatedFieldsMessage) {
          return MergeFrom((DeprecatedFieldsMessage) other);
        } else {
          base.MergeFrom(other);
          return this;
        }
      }
      
      public override Builder MergeFrom(DeprecatedFieldsMessage other) {
        if (other == global::UnitTest.Issues.TestProtos.DeprecatedFieldsMessage.DefaultInstance) return this;
        if (other.HasPrimitiveValue) {
          PrimitiveValue = other.PrimitiveValue;
        }
        if (other.primitiveArray_.Count != 0) {
          base.AddRange(other.primitiveArray_, result.primitiveArray_);
        }
        if (other.HasMessageValue) {
          MergeMessageValue(other.MessageValue);
        }
        if (other.messageArray_.Count != 0) {
          base.AddRange(other.messageArray_, result.messageArray_);
        }
        if (other.HasEnumValue) {
          EnumValue = other.EnumValue;
        }
        if (other.enumArray_.Count != 0) {
          base.AddRange(other.enumArray_, result.enumArray_);
        }
        this.MergeUnknownFields(other.UnknownFields);
        return this;
      }
      
      public override Builder MergeFrom(pb::ICodedInputStream input) {
        return MergeFrom(input, pb::ExtensionRegistry.Empty);
      }
      
      public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {
        pb::UnknownFieldSet.Builder unknownFields = null;
        uint tag;
        string field_name;
        while (input.ReadTag(out tag, out field_name)) {
          if(tag == 0 && field_name != null) {
            int field_ordinal = global::System.Array.BinarySearch(_deprecatedFieldsMessageFieldNames, field_name, global::System.StringComparer.Ordinal);
            if(field_ordinal >= 0)
              tag = _deprecatedFieldsMessageFieldTags[field_ordinal];
            else {
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              continue;
            }
          }
          switch (tag) {
            case 0: {
              throw pb::InvalidProtocolBufferException.InvalidTag();
            }
            default: {
              if (pb::WireFormat.IsEndGroupTag(tag)) {
                if (unknownFields != null) {
                  this.UnknownFields = unknownFields.Build();
                }
                return this;
              }
              if (unknownFields == null) {
                unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
              }
              ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name);
              break;
            }
            case 8: {
              result.hasPrimitiveValue = input.ReadInt32(ref result.primitiveValue_);
              break;
            }
            case 18:
            case 16: {
              input.ReadInt32Array(tag, field_name, result.primitiveArray_);
              break;
            }
            case 26: {
              global::UnitTest.Issues.TestProtos.DeprecatedChild.Builder subBuilder = global::UnitTest.Issues.TestProtos.DeprecatedChild.CreateBuilder();
              if (result.hasMessageValue) {
                subBuilder.MergeFrom(MessageValue);
              }
              input.ReadMessage(subBuilder, extensionRegistry);
              MessageValue = subBuilder.BuildPartial();
              break;
            }
            case 34: {
              input.ReadMessageArray(tag, field_name, result.messageArray_, global::UnitTest.Issues.TestProtos.DeprecatedChild.DefaultInstance, extensionRegistry);
              break;
            }
            case 40: {
              object unknown;
              if(input.ReadEnum(ref result.enumValue_, out unknown)) {
                result.hasEnumValue = true;
              } else if(unknown is int) {
                if (unknownFields == null) {
                  unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                }
                unknownFields.MergeVarintField(5, (ulong)(int)unknown);
              }
              break;
            }
            case 50:
            case 48: {
              scg::ICollection<object> unknownItems;
              input.ReadEnumArray<global::UnitTest.Issues.TestProtos.DeprecatedEnum>(tag, field_name, result.enumArray_, out unknownItems);
              if (unknownItems != null) {
                if (unknownFields == null) {
                  unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);
                }
                foreach (object rawValue in unknownItems)
                  if (rawValue is int)
                    unknownFields.MergeVarintField(6, (ulong)(int)rawValue);
              }
              break;
            }
          }
        }
        
        if (unknownFields != null) {
          this.UnknownFields = unknownFields.Build();
        }
        return this;
      }
      
      
      [global::System.ObsoleteAttribute()]
      public bool HasPrimitiveValue {
        get { return result.hasPrimitiveValue; }
      }
      [global::System.ObsoleteAttribute()]
      public int PrimitiveValue {
        get { return result.PrimitiveValue; }
        set { SetPrimitiveValue(value); }
      }
      [global::System.ObsoleteAttribute()]
      public Builder SetPrimitiveValue(int value) {
        result.hasPrimitiveValue = true;
        result.primitiveValue_ = value;
        return this;
      }
      [global::System.ObsoleteAttribute()]
      public Builder ClearPrimitiveValue() {
        result.hasPrimitiveValue = false;
        result.primitiveValue_ = 0;
        return this;
      }
      
      [global::System.ObsoleteAttribute()]
      public pbc::IPopsicleList<int> PrimitiveArrayList {
        get { return result.primitiveArray_; }
      }
      [global::System.ObsoleteAttribute()]
      public int PrimitiveArrayCount {
        get { return result.PrimitiveArrayCount; }
      }
      [global::System.ObsoleteAttribute()]
      public int GetPrimitiveArray(int index) {
        return result.GetPrimitiveArray(index);
      }
      [global::System.ObsoleteAttribute()]
      public Builder SetPrimitiveArray(int index, int value) {
        result.primitiveArray_[index] = value;
        return this;
      }
      [global::System.ObsoleteAttribute()]
      public Builder AddPrimitiveArray(int value) {
        result.primitiveArray_.Add(value);
        return this;
      }
      [global::System.ObsoleteAttribute()]
      public Builder AddRangePrimitiveArray(scg::IEnumerable<int> values) {
        base.AddRange(values, result.primitiveArray_);
        return this;
      }
      [global::System.ObsoleteAttribute()]
      public Builder ClearPrimitiveArray() {
        result.primitiveArray_.Clear();
        return this;
      }
      
      [global::System.ObsoleteAttribute()]
      public bool HasMessageValue {
       get { return result.hasMessageValue; }
      }
      [global::System.ObsoleteAttribute()]
      public global::UnitTest.Issues.TestProtos.DeprecatedChild MessageValue {
        get { return result.MessageValue; }
        set { SetMessageValue(value); }
      }
      [global::System.ObsoleteAttribute()]
      public Builder SetMessageValue(global::UnitTest.Issues.TestProtos.DeprecatedChild value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        result.hasMessageValue = true;
        result.messageValue_ = value;
        return this;
      }
      [global::System.ObsoleteAttribute()]
      public Builder SetMessageValue(global::UnitTest.Issues.TestProtos.DeprecatedChild.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        result.hasMessageValue = true;
        result.messageValue_ = builderForValue.Build();
        return this;
      }
      [global::System.ObsoleteAttribute()]
      public Builder MergeMessageValue(global::UnitTest.Issues.TestProtos.DeprecatedChild value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        if (result.hasMessageValue &&
            result.messageValue_ != global::UnitTest.Issues.TestProtos.DeprecatedChild.DefaultInstance) {
            result.messageValue_ = global::UnitTest.Issues.TestProtos.DeprecatedChild.CreateBuilder(result.messageValue_).MergeFrom(value).BuildPartial();
        } else {
          result.messageValue_ = value;
        }
        result.hasMessageValue = true;
        return this;
      }
      [global::System.ObsoleteAttribute()]
      public Builder ClearMessageValue() {
        result.hasMessageValue = false;
        result.messageValue_ = global::UnitTest.Issues.TestProtos.DeprecatedChild.DefaultInstance;
        return this;
      }
      
      [global::System.ObsoleteAttribute()]
      public pbc::IPopsicleList<global::UnitTest.Issues.TestProtos.DeprecatedChild> MessageArrayList {
        get { return result.messageArray_; }
      }
      [global::System.ObsoleteAttribute()]
      public int MessageArrayCount {
        get { return result.MessageArrayCount; }
      }
      [global::System.ObsoleteAttribute()]
      public global::UnitTest.Issues.TestProtos.DeprecatedChild GetMessageArray(int index) {
        return result.GetMessageArray(index);
      }
      [global::System.ObsoleteAttribute()]
      public Builder SetMessageArray(int index, global::UnitTest.Issues.TestProtos.DeprecatedChild value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        result.messageArray_[index] = value;
        return this;
      }
      [global::System.ObsoleteAttribute()]
      public Builder SetMessageArray(int index, global::UnitTest.Issues.TestProtos.DeprecatedChild.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        result.messageArray_[index] = builderForValue.Build();
        return this;
      }
      [global::System.ObsoleteAttribute()]
      public Builder AddMessageArray(global::UnitTest.Issues.TestProtos.DeprecatedChild value) {
        pb::ThrowHelper.ThrowIfNull(value, "value");
        result.messageArray_.Add(value);
        return this;
      }
      [global::System.ObsoleteAttribute()]
      public Builder AddMessageArray(global::UnitTest.Issues.TestProtos.DeprecatedChild.Builder builderForValue) {
        pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue");
        result.messageArray_.Add(builderForValue.Build());
        return this;
      }
      [global::System.ObsoleteAttribute()]
      public Builder AddRangeMessageArray(scg::IEnumerable<global::UnitTest.Issues.TestProtos.DeprecatedChild> values) {
        base.AddRange(values, result.messageArray_);
        return this;
      }
      [global::System.ObsoleteAttribute()]
      public Builder ClearMessageArray() {
        result.messageArray_.Clear();
        return this;
      }
      
      [global::System.ObsoleteAttribute()]
      public bool HasEnumValue {
       get { return result.hasEnumValue; }
      }
      [global::System.ObsoleteAttribute()]
      public global::UnitTest.Issues.TestProtos.DeprecatedEnum EnumValue {
        get { return result.EnumValue; }
        set { SetEnumValue(value); }
      }
      [global::System.ObsoleteAttribute()]
      public Builder SetEnumValue(global::UnitTest.Issues.TestProtos.DeprecatedEnum value) {
        result.hasEnumValue = true;
        result.enumValue_ = value;
        return this;
      }
      [global::System.ObsoleteAttribute()]
      public Builder ClearEnumValue() {
        result.hasEnumValue = false;
        result.enumValue_ = global::UnitTest.Issues.TestProtos.DeprecatedEnum.one;
        return this;
      }
      
      [global::System.ObsoleteAttribute()]
      public pbc::IPopsicleList<global::UnitTest.Issues.TestProtos.DeprecatedEnum> EnumArrayList {
        get { return result.enumArray_; }
      }
      [global::System.ObsoleteAttribute()]
      public int EnumArrayCount {
        get { return result.EnumArrayCount; }
      }
      [global::System.ObsoleteAttribute()]
      public global::UnitTest.Issues.TestProtos.DeprecatedEnum GetEnumArray(int index) {
        return result.GetEnumArray(index);
      }
      [global::System.ObsoleteAttribute()]
      public Builder SetEnumArray(int index, global::UnitTest.Issues.TestProtos.DeprecatedEnum value) {
        result.enumArray_[index] = value;
        return this;
      }
      [global::System.ObsoleteAttribute()]
      public Builder AddEnumArray(global::UnitTest.Issues.TestProtos.DeprecatedEnum value) {
        result.enumArray_.Add(value);
        return this;
      }
      [global::System.ObsoleteAttribute()]
      public Builder AddRangeEnumArray(scg::IEnumerable<global::UnitTest.Issues.TestProtos.DeprecatedEnum> values) {
        base.AddRange(values, result.enumArray_);
        return this;
      }
      [global::System.ObsoleteAttribute()]
      public Builder ClearEnumArray() {
        result.enumArray_.Clear();
        return this;
      }
    }
    static DeprecatedFieldsMessage() {
      object.ReferenceEquals(global::UnitTest.Issues.TestProtos.UnitTestExtrasIssuesProtoFile.Descriptor, null);
    }
  }
  
  #endregion
  
}

#endregion Designer generated code
