diff --git a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.Proto2.cs b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.Proto2.cs
index e1d4d7809ad6..718c3edcb80e 100644
--- a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.Proto2.cs
+++ b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.Proto2.cs
@@ -261,6 +261,18 @@ public void RequiredFields()
Assert.True(message.IsInitialized());
}
+ ///
+ /// Code was accidentally left in message parser that threw exceptions when missing required fields after parsing.
+ /// We've decided to not throw exceptions on missing fields, instead leaving it up to the consumer how they
+ /// want to check and handle missing fields.
+ ///
+ [Test]
+ public void RequiredFieldsNoThrow()
+ {
+ Assert.DoesNotThrow(() => TestRequired.Parser.ParseFrom(new byte[0]));
+ Assert.DoesNotThrow(() => (TestRequired.Parser as MessageParser).ParseFrom(new byte[0]));
+ }
+
[Test]
public void RequiredFieldsInExtensions()
{
diff --git a/csharp/src/Google.Protobuf/CodedOutputStream.cs b/csharp/src/Google.Protobuf/CodedOutputStream.cs
index f9ad29086bda..1d76d276029d 100644
--- a/csharp/src/Google.Protobuf/CodedOutputStream.cs
+++ b/csharp/src/Google.Protobuf/CodedOutputStream.cs
@@ -89,7 +89,7 @@ public CodedOutputStream(byte[] flatArray) : this(flatArray, 0, flatArray.Length
private CodedOutputStream(byte[] buffer, int offset, int length)
{
this.output = null;
- this.buffer = buffer;
+ this.buffer = ProtoPreconditions.CheckNotNull(buffer, nameof(buffer));
this.position = offset;
this.limit = offset + length;
leaveOpen = true; // Simple way of avoiding trying to dispose of a null reference
diff --git a/csharp/src/Google.Protobuf/JsonFormatter.cs b/csharp/src/Google.Protobuf/JsonFormatter.cs
index 2b4c5f0a8038..5aaefe7a890f 100644
--- a/csharp/src/Google.Protobuf/JsonFormatter.cs
+++ b/csharp/src/Google.Protobuf/JsonFormatter.cs
@@ -133,7 +133,7 @@ static JsonFormatter()
/// The settings.
public JsonFormatter(Settings settings)
{
- this.settings = settings;
+ this.settings = ProtoPreconditions.CheckNotNull(settings, nameof(settings));
}
///
diff --git a/csharp/src/Google.Protobuf/JsonParser.cs b/csharp/src/Google.Protobuf/JsonParser.cs
index fb594f2a4343..3f88ea38f177 100644
--- a/csharp/src/Google.Protobuf/JsonParser.cs
+++ b/csharp/src/Google.Protobuf/JsonParser.cs
@@ -110,7 +110,7 @@ private static void MergeWrapperField(JsonParser parser, IMessage message, JsonT
/// The settings.
public JsonParser(Settings settings)
{
- this.settings = settings;
+ this.settings = ProtoPreconditions.CheckNotNull(settings, nameof(settings));
}
///
diff --git a/csharp/src/Google.Protobuf/MessageParser.cs b/csharp/src/Google.Protobuf/MessageParser.cs
index 76a350ce4c61..06d0f1059c7a 100644
--- a/csharp/src/Google.Protobuf/MessageParser.cs
+++ b/csharp/src/Google.Protobuf/MessageParser.cs
@@ -72,7 +72,6 @@ public IMessage ParseFrom(byte[] data)
{
IMessage message = factory();
message.MergeFrom(data, DiscardUnknownFields, Extensions);
- CheckMergedRequiredFields(message);
return message;
}
@@ -87,7 +86,6 @@ public IMessage ParseFrom(byte[] data, int offset, int length)
{
IMessage message = factory();
message.MergeFrom(data, offset, length, DiscardUnknownFields, Extensions);
- CheckMergedRequiredFields(message);
return message;
}
@@ -100,7 +98,6 @@ public IMessage ParseFrom(ByteString data)
{
IMessage message = factory();
message.MergeFrom(data, DiscardUnknownFields, Extensions);
- CheckMergedRequiredFields(message);
return message;
}
@@ -113,7 +110,6 @@ public IMessage ParseFrom(Stream input)
{
IMessage message = factory();
message.MergeFrom(input, DiscardUnknownFields, Extensions);
- CheckMergedRequiredFields(message);
return message;
}
@@ -130,7 +126,6 @@ public IMessage ParseDelimitedFrom(Stream input)
{
IMessage message = factory();
message.MergeDelimitedFrom(input, DiscardUnknownFields, Extensions);
- CheckMergedRequiredFields(message);
return message;
}
@@ -143,7 +138,6 @@ public IMessage ParseFrom(CodedInputStream input)
{
IMessage message = factory();
MergeFrom(message, input);
- CheckMergedRequiredFields(message);
return message;
}
@@ -176,12 +170,6 @@ internal void MergeFrom(IMessage message, CodedInputStream codedInput)
}
}
- internal static void CheckMergedRequiredFields(IMessage message)
- {
- if (!message.IsInitialized())
- throw new InvalidOperationException("Parsed message does not contain all required fields");
- }
-
///
/// Creates a new message parser which optionally discards unknown fields when parsing.
///
diff --git a/csharp/src/Google.Protobuf/Reflection/ExtensionCollection.cs b/csharp/src/Google.Protobuf/Reflection/ExtensionCollection.cs
index 38e33d7ff2bd..9664559df249 100644
--- a/csharp/src/Google.Protobuf/Reflection/ExtensionCollection.cs
+++ b/csharp/src/Google.Protobuf/Reflection/ExtensionCollection.cs
@@ -107,13 +107,14 @@ internal void CrossLink()
{
descriptor.CrossLink();
- IList _;
- if (!declarationOrder.TryGetValue(descriptor.ExtendeeType, out _))
+ IList list;
+ if (!declarationOrder.TryGetValue(descriptor.ExtendeeType, out list))
{
- declarationOrder.Add(descriptor.ExtendeeType, new List());
+ list = new List();
+ declarationOrder.Add(descriptor.ExtendeeType, list);
}
- declarationOrder[descriptor.ExtendeeType].Add(descriptor);
+ list.Add(descriptor);
}
extensionsByTypeInDeclarationOrder = declarationOrder