diff options
Diffstat (limited to 'csharp')
8 files changed, 6 insertions, 259 deletions
diff --git a/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs b/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs index 46d3bd9a..c62ac046 100644 --- a/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs +++ b/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs @@ -45,53 +45,6 @@ namespace Google.Protobuf.Collections /// </summary> public class MapFieldTest { - // Protobuf-specific tests - [Test] - public void Freeze_FreezesMessages() - { - var message = new ForeignMessage { C = 20 }; - var map = new MapField<string, ForeignMessage> { { "x", message } }; - map.Freeze(); - Assert.IsTrue(message.IsFrozen); - } - - [Test] - public void Freeze_Idempotent() - { - var message = new ForeignMessage { C = 20 }; - var map = new MapField<string, ForeignMessage> { { "x", message } }; - Assert.IsFalse(map.IsFrozen); - map.Freeze(); - Assert.IsTrue(message.IsFrozen); - map.Freeze(); - Assert.IsTrue(message.IsFrozen); - } - - [Test] - public void Freeze_PreventsMutation() - { - var map = new MapField<string, string>(); - map.Freeze(); - Assert.IsTrue(map.IsFrozen); - Assert.IsTrue(map.IsReadOnly); - ICollection<KeyValuePair<string, string>> collection = map; - Assert.Throws<InvalidOperationException>(() => map["x"] = "y"); - Assert.Throws<InvalidOperationException>(() => map.Add("x", "y")); - Assert.Throws<InvalidOperationException>(() => map.Remove("x")); - Assert.Throws<InvalidOperationException>(() => map.Clear()); - Assert.Throws<InvalidOperationException>(() => collection.Add(NewKeyValuePair("x", "y"))); - Assert.Throws<InvalidOperationException>(() => collection.Remove(NewKeyValuePair("x", "y"))); - } - - [Test] - public void Clone_ReturnsNonFrozen() - { - var map = new MapField<string, string>(); - map.Freeze(); - var clone = map.Clone(); - clone.Add("x", "y"); - } - [Test] public void Clone_ClonesMessages() { @@ -422,10 +375,6 @@ namespace Google.Protobuf.Collections dictionary.Remove("x"); Assert.AreEqual(0, dictionary.Count); Assert.Throws<ArgumentNullException>(() => dictionary.Remove(null)); - - map.Freeze(); - // Call should fail even though it clearly doesn't contain 5 as a key. - Assert.Throws<InvalidOperationException>(() => dictionary.Remove(5)); } [Test] @@ -449,8 +398,6 @@ namespace Google.Protobuf.Collections var map = new MapField<string, string> { { "x", "y" } }; IDictionary dictionary = map; Assert.IsFalse(dictionary.IsFixedSize); - map.Freeze(); - Assert.IsTrue(dictionary.IsFixedSize); } [Test] @@ -504,9 +451,6 @@ namespace Google.Protobuf.Collections Assert.Throws<InvalidCastException>(() => dictionary["x"] = 5); Assert.Throws<ArgumentNullException>(() => dictionary[null] = "z"); Assert.Throws<ArgumentNullException>(() => dictionary["x"] = null); - map.Freeze(); - // Note: Not InvalidOperationException. - Assert.Throws<NotSupportedException>(() => dictionary["a"] = "c"); } [Test] diff --git a/csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs b/csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs index 25be7731..33c4e10c 100644 --- a/csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs +++ b/csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs @@ -194,43 +194,9 @@ namespace Google.Protobuf.Collections } [Test] - public void Freeze_FreezesElements() - { - var list = new RepeatedField<TestAllTypes> { new TestAllTypes() }; - Assert.IsFalse(list[0].IsFrozen); - list.Freeze(); - Assert.IsTrue(list[0].IsFrozen); - } - - [Test] - public void Freeze_PreventsMutations() - { - var list = new RepeatedField<int> { 0 }; - list.Freeze(); - Assert.Throws<InvalidOperationException>(() => list.Add(1)); - Assert.Throws<InvalidOperationException>(() => list[0] = 1); - Assert.Throws<InvalidOperationException>(() => list.Clear()); - Assert.Throws<InvalidOperationException>(() => list.RemoveAt(0)); - Assert.Throws<InvalidOperationException>(() => list.Remove(0)); - Assert.Throws<InvalidOperationException>(() => list.Insert(0, 0)); - } - - [Test] - public void Freeze_ReportsFrozen() - { - var list = new RepeatedField<int> { 0 }; - Assert.IsFalse(list.IsFrozen); - Assert.IsFalse(list.IsReadOnly); - list.Freeze(); - Assert.IsTrue(list.IsFrozen); - Assert.IsTrue(list.IsReadOnly); - } - - [Test] public void Clone_ReturnsMutable() { var list = new RepeatedField<int> { 0 }; - list.Freeze(); var clone = list.Clone(); clone[0] = 1; } @@ -585,8 +551,6 @@ namespace Google.Protobuf.Collections var field = new RepeatedField<string> { "first", "second" }; IList list = field; Assert.IsFalse(list.IsFixedSize); - field.Freeze(); - Assert.IsTrue(list.IsFixedSize); } [Test] diff --git a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs index 528a4023..dfaac48c 100644 --- a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs +++ b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs @@ -504,23 +504,6 @@ namespace Google.Protobuf }
[Test]
- public void Freeze()
- {
- var frozen = new TestAllTypes();
- frozen.Freeze();
- Assert.IsTrue(frozen.IsFrozen);
-
- Assert.Throws<InvalidOperationException>(() => frozen.ClearOneofField());
- Assert.Throws<InvalidOperationException>(() => frozen.SingleInt32 = 0);
- Assert.Throws<InvalidOperationException>(() => frozen.SingleNestedMessage = null);
- Assert.Throws<InvalidOperationException>(() => frozen.SingleNestedEnum = 0);
- Assert.Throws<InvalidOperationException>(() => frozen.OneofString = null);
- Assert.Throws<InvalidOperationException>(() => frozen.OneofUint32 = 0U);
- Assert.Throws<InvalidOperationException>(() => frozen.RepeatedDouble.Add(0.0));
- Assert.Throws<InvalidOperationException>(() => frozen.RepeatedNestedMessage.Add(new TestAllTypes.Types.NestedMessage()));
- }
-
- [Test]
public void OneofProperties()
{
// Switch the oneof case between each of the different options, and check everything behaves
diff --git a/csharp/src/Google.Protobuf/Collections/MapField.cs b/csharp/src/Google.Protobuf/Collections/MapField.cs index 68f2f1cc..0f7227c2 100644 --- a/csharp/src/Google.Protobuf/Collections/MapField.cs +++ b/csharp/src/Google.Protobuf/Collections/MapField.cs @@ -50,7 +50,7 @@ namespace Google.Protobuf.Collections /// </remarks> /// <typeparam name="TKey">Key type in the map. Must be a type supported by Protocol Buffer map keys.</typeparam> /// <typeparam name="TValue">Value type in the map. Must be a type supported by Protocol Buffers.</typeparam> - public sealed class MapField<TKey, TValue> : IDeepCloneable<MapField<TKey, TValue>>, IFreezable, IDictionary<TKey, TValue>, IEquatable<MapField<TKey, TValue>>, IDictionary + public sealed class MapField<TKey, TValue> : IDeepCloneable<MapField<TKey, TValue>>, IDictionary<TKey, TValue>, IEquatable<MapField<TKey, TValue>>, IDictionary { // TODO: Don't create the map/list until we have an entry. (Assume many maps will be empty.) private readonly bool allowNullValues; @@ -119,7 +119,6 @@ namespace Google.Protobuf.Collections public bool Remove(TKey key) { - this.CheckMutable(); ThrowHelper.ThrowIfNull(key, "key"); LinkedListNode<KeyValuePair<TKey, TValue>> node; if (map.TryGetValue(key, out node)) @@ -169,7 +168,6 @@ namespace Google.Protobuf.Collections { ThrowHelper.ThrowIfNull(value, "value"); } - this.CheckMutable(); LinkedListNode<KeyValuePair<TKey, TValue>> node; var pair = new KeyValuePair<TKey, TValue>(key, value); if (map.TryGetValue(key, out node)) @@ -214,7 +212,6 @@ namespace Google.Protobuf.Collections public void Clear() { - this.CheckMutable(); list.Clear(); map.Clear(); } @@ -233,7 +230,6 @@ namespace Google.Protobuf.Collections bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item) { - this.CheckMutable(); if (item.Key == null) { throw new ArgumentException("Key is null", "item"); @@ -260,31 +256,6 @@ namespace Google.Protobuf.Collections public int Count { get { return list.Count; } } public bool IsReadOnly { get { return frozen; } } - public void Freeze() - { - if (IsFrozen) - { - return; - } - frozen = true; - // Only values can be frozen, as all the key types are simple. - // Everything can be done in-place, as we're just freezing objects. - if (typeof(IFreezable).IsAssignableFrom(typeof(TValue))) - { - for (var node = list.First; node != null; node = node.Next) - { - var pair = node.Value; - IFreezable freezableValue = pair.Value as IFreezable; - if (freezableValue != null) - { - freezableValue.Freeze(); - } - } - } - } - - public bool IsFrozen { get { return frozen; } } - public override bool Equals(object other) { return Equals(other as MapField<TKey, TValue>); @@ -405,7 +376,6 @@ namespace Google.Protobuf.Collections void IDictionary.Remove(object key) { ThrowHelper.ThrowIfNull(key, "key"); - this.CheckMutable(); if (!(key is TKey)) { return; @@ -420,7 +390,7 @@ namespace Google.Protobuf.Collections temp.CopyTo(array, index); } - bool IDictionary.IsFixedSize { get { return IsFrozen; } } + bool IDictionary.IsFixedSize { get { return false; } } ICollection IDictionary.Keys { get { return (ICollection)Keys; } } diff --git a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs index ccd1a9bb..e7fc0a3f 100644 --- a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs +++ b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs @@ -43,7 +43,7 @@ namespace Google.Protobuf.Collections /// restrictions (no null values) and capabilities (deep cloning and freezing). /// </summary> /// <typeparam name="T">The element type of the repeated field.</typeparam> - public sealed class RepeatedField<T> : IList<T>, IList, IDeepCloneable<RepeatedField<T>>, IEquatable<RepeatedField<T>>, IFreezable + public sealed class RepeatedField<T> : IList<T>, IList, IDeepCloneable<RepeatedField<T>>, IEquatable<RepeatedField<T>> { private static readonly T[] EmptyArray = new T[0]; private const int MinArraySize = 8; @@ -190,21 +190,6 @@ namespace Google.Protobuf.Collections } } - public bool IsFrozen { get { return frozen; } } - - public void Freeze() - { - frozen = true; - IFreezable[] freezableArray = array as IFreezable[]; - if (freezableArray != null) - { - for (int i = 0; i < count; i++) - { - freezableArray[i].Freeze(); - } - } - } - private void EnsureSize(int size) { if (array.Length < size) @@ -223,14 +208,12 @@ namespace Google.Protobuf.Collections { throw new ArgumentNullException("item"); } - this.CheckMutable(); EnsureSize(count + 1); array[count++] = item; } public void Clear() { - this.CheckMutable(); array = EmptyArray; count = 0; } @@ -247,7 +230,6 @@ namespace Google.Protobuf.Collections public bool Remove(T item) { - this.CheckMutable(); int index = IndexOf(item); if (index == -1) { @@ -261,7 +243,7 @@ namespace Google.Protobuf.Collections public int Count { get { return count; } } - public bool IsReadOnly { get { return IsFrozen; } } + public bool IsReadOnly { get { return false; } } public void Add(RepeatedField<T> values) { @@ -269,7 +251,6 @@ namespace Google.Protobuf.Collections { throw new ArgumentNullException("values"); } - this.CheckMutable(); EnsureSize(count + values.count); // We know that all the values will be valid, because it's a RepeatedField. Array.Copy(values.array, 0, array, count, values.count); @@ -282,7 +263,6 @@ namespace Google.Protobuf.Collections { throw new ArgumentNullException("values"); } - this.CheckMutable(); // TODO: Check for ICollection and get the Count? foreach (T item in values) { @@ -372,7 +352,6 @@ namespace Google.Protobuf.Collections { throw new ArgumentOutOfRangeException("index"); } - this.CheckMutable(); EnsureSize(count + 1); Array.Copy(array, index, array, index + 1, count - index); array[index] = item; @@ -385,7 +364,6 @@ namespace Google.Protobuf.Collections { throw new ArgumentOutOfRangeException("index"); } - this.CheckMutable(); Array.Copy(array, index + 1, array, index, count - index - 1); count--; array[count] = default(T); @@ -407,7 +385,6 @@ namespace Google.Protobuf.Collections { throw new ArgumentOutOfRangeException("index"); } - this.CheckMutable(); if (value == null) { throw new ArgumentNullException("value"); @@ -417,7 +394,7 @@ namespace Google.Protobuf.Collections } #region Explicit interface implementation for IList and ICollection. - bool IList.IsFixedSize { get { return IsFrozen; } } + bool IList.IsFixedSize { get { return false; } } void ICollection.CopyTo(Array array, int index) { diff --git a/csharp/src/Google.Protobuf/Freezable.cs b/csharp/src/Google.Protobuf/Freezable.cs deleted file mode 100644 index d16e1b42..00000000 --- a/csharp/src/Google.Protobuf/Freezable.cs +++ /dev/null @@ -1,58 +0,0 @@ -#region Copyright notice and license -// Protocol Buffers - Google's data interchange format -// Copyright 2015 Google Inc. All rights reserved. -// https://developers.google.com/protocol-buffers/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#endregion - -using System; - -namespace Google.Protobuf -{ - /// <summary> - /// Extension methods for <see cref="IFreezable"/> types. - /// </summary> - public static class Freezable - { - /// <summary> - /// Throws an <see cref="InvalidOperationException"/> if <paramref name="target"/> - /// is frozen. - /// </summary> - /// <remarks> - /// This is a convenience methods that freezable types can call before all - /// mutations, to protect frozen objects. - /// </remarks> - public static void CheckMutable(this IFreezable target) - { - if (target.IsFrozen) - { - throw new InvalidOperationException("Attempt to mutate frozen object"); - } - } - } -} diff --git a/csharp/src/Google.Protobuf/Google.Protobuf.csproj b/csharp/src/Google.Protobuf/Google.Protobuf.csproj index b1f20816..b141e434 100644 --- a/csharp/src/Google.Protobuf/Google.Protobuf.csproj +++ b/csharp/src/Google.Protobuf/Google.Protobuf.csproj @@ -64,7 +64,6 @@ <Compile Include="Compatibility\TypeExtensions.cs" />
<Compile Include="FieldCodec.cs" />
<Compile Include="FrameworkPortability.cs" />
- <Compile Include="Freezable.cs" />
<Compile Include="JsonFormatter.cs" />
<Compile Include="MessageExtensions.cs" />
<Compile Include="IMessage.cs" />
diff --git a/csharp/src/Google.Protobuf/IMessage.cs b/csharp/src/Google.Protobuf/IMessage.cs index d179c386..60c6f8c3 100644 --- a/csharp/src/Google.Protobuf/IMessage.cs +++ b/csharp/src/Google.Protobuf/IMessage.cs @@ -79,7 +79,7 @@ namespace Google.Protobuf /// the implementation class.
/// </summary>
/// <typeparam name="T">The message type.</typeparam>
- public interface IMessage<T> : IMessage, IEquatable<T>, IDeepCloneable<T>, IFreezable where T : IMessage<T>
+ public interface IMessage<T> : IMessage, IEquatable<T>, IDeepCloneable<T> where T : IMessage<T>
{
/// <summary>
/// Merges the given message into this one.
@@ -97,10 +97,6 @@ namespace Google.Protobuf /// Additionally, due to the type constraint on <c>T</c> in <see cref="IMessage{T}"/>,
/// it is simpler to keep this as a separate interface.
/// </para>
- /// <para>
- /// Freezable types which implement this interface should always return a mutable clone,
- /// even if the original object is frozen.
- /// </para>
/// </remarks>
/// <typeparam name="T">The type itself, returned by the <see cref="Clone"/> method.</typeparam>
public interface IDeepCloneable<T>
@@ -111,32 +107,4 @@ namespace Google.Protobuf /// <returns>A deep clone of this object.</returns>
T Clone();
}
-
- /// <summary>
- /// Provides a mechanism for freezing a message (or repeated field collection)
- /// to make it immutable.
- /// </summary>
- /// <remarks>
- /// Implementations are under no obligation to make this thread-safe: if a freezable
- /// type instance is shared between threads before being frozen, and one thread then
- /// freezes it, it is possible for other threads to make changes during the freezing
- /// operation and also to observe stale values for mutated fields. Objects should be
- /// frozen before being made available to other threads.
- /// </remarks>
- public interface IFreezable
- {
- /// <summary>
- /// Freezes this object.
- /// </summary>
- /// <remarks>
- /// If the object is already frozen, this method has no effect.
- /// </remarks>
- void Freeze();
-
- /// <summary>
- /// Returns whether or not this object is frozen (and therefore immutable).
- /// </summary>
- /// <value><c>true</c> if this object is frozen; <c>false</c> otherwise.</value>
- bool IsFrozen { get; }
- }
}
|