diff --git a/src/Umbraco.Core/Collections/CompositeNStringNStringKey.cs b/src/Umbraco.Core/Collections/CompositeNStringNStringKey.cs
new file mode 100644
index 0000000000..a06696f6c6
--- /dev/null
+++ b/src/Umbraco.Core/Collections/CompositeNStringNStringKey.cs
@@ -0,0 +1,41 @@
+using System;
+
+namespace Umbraco.Core.Collections
+{
+ ///
+ /// Represents a composite key of (string, string) for fast dictionaries.
+ ///
+ ///
+ /// The string parts of the key are case-insensitive.
+ /// Null is a valid value for both parts.
+ ///
+ public struct CompositeNStringNStringKey : IEquatable
+ {
+ private readonly string _key1;
+ private readonly string _key2;
+
+ ///
+ /// Initializes a new instance of the struct.
+ ///
+ public CompositeNStringNStringKey(string key1, string key2)
+ {
+ _key1 = key1?.ToLowerInvariant() ?? "NULL";
+ _key2 = key2?.ToLowerInvariant() ?? "NULL";
+ }
+
+ public bool Equals(CompositeNStringNStringKey other)
+ => _key2 == other._key2 && _key1 == other._key1;
+
+ public override bool Equals(object obj)
+ => obj is CompositeNStringNStringKey other && _key2 == other._key2 && _key1 == other._key1;
+
+ public override int GetHashCode()
+ => _key2.GetHashCode() * 31 + _key1.GetHashCode();
+
+ public static bool operator ==(CompositeNStringNStringKey key1, CompositeNStringNStringKey key2)
+ => key1._key2 == key2._key2 && key1._key1 == key2._key1;
+
+ public static bool operator !=(CompositeNStringNStringKey key1, CompositeNStringNStringKey key2)
+ => key1._key2 != key2._key2 || key1._key1 != key2._key1;
+ }
+}
\ No newline at end of file
diff --git a/src/Umbraco.Core/Collections/CompositeStringStringKey.cs b/src/Umbraco.Core/Collections/CompositeStringStringKey.cs
index 78ee9b0d2a..c053b08a22 100644
--- a/src/Umbraco.Core/Collections/CompositeStringStringKey.cs
+++ b/src/Umbraco.Core/Collections/CompositeStringStringKey.cs
@@ -7,7 +7,7 @@ namespace Umbraco.Core.Collections
///
///
/// The string parts of the key are case-insensitive.
- /// Null is a valid value for both parts.
+ /// Null is NOT a valid value for neither parts.
///
public struct CompositeStringStringKey : IEquatable
{
@@ -19,12 +19,8 @@ namespace Umbraco.Core.Collections
///
public CompositeStringStringKey(string key1, string key2)
{
- // fixme temp - debugging
- if (key1 == null) throw new Exception("Getting null culture in CompositeStringStringKey constructor, fix!");
- if (key2 == null) throw new Exception("Getting null segment in CompositeStringStringKey constructor, fix!");
-
- _key1 = key1?.ToLowerInvariant() ?? "NULL";
- _key2 = key2?.ToLowerInvariant() ?? "NULL";
+ _key1 = key1?.ToLowerInvariant() ?? throw new ArgumentNullException(nameof(key1));
+ _key2 = key2?.ToLowerInvariant() ?? throw new ArgumentNullException(nameof(key2));
}
public bool Equals(CompositeStringStringKey other)
diff --git a/src/Umbraco.Core/Models/Property.cs b/src/Umbraco.Core/Models/Property.cs
index 7e53eb764a..19a63925df 100644
--- a/src/Umbraco.Core/Models/Property.cs
+++ b/src/Umbraco.Core/Models/Property.cs
@@ -18,7 +18,7 @@ namespace Umbraco.Core.Models
{
private List _values = new List();
private PropertyValue _pvalue;
- private Dictionary _vvalues;
+ private Dictionary _vvalues;
private static readonly Lazy Ps = new Lazy();
@@ -77,8 +77,8 @@ namespace Umbraco.Core.Models
// custom comparer for enumerable
// ReSharper disable once MergeCastWithTypeCheck
- if (o is IEnumerable && o1 is IEnumerable)
- return ((IEnumerable) o).Cast