1010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1111*/
1212
13+ // define to enable checks for a null NodeId modification
14+ // some tests are failing with this enabled, only turn on to catch issues
15+ // #define IMMUTABLENULLNODEID
16+
1317using System ;
1418using System . Collections ;
1519using System . Collections . Generic ;
@@ -866,8 +870,11 @@ internal static NodeId InternalParse(string text, bool namespaceSet)
866870 /// Returns an instance of a null NodeId.
867871 /// </summary>
868872 public static NodeId Null => s_Null ;
869-
873+ #if IMMUTABLENULLNODEID
874+ private static readonly NodeId s_Null = new ImmutableNodeId ( ) ;
875+ #else
870876 private static readonly NodeId s_Null = new NodeId ( ) ;
877+ #endif
871878 #endregion
872879
873880 #region Public Methods (and some Internals)
@@ -1001,6 +1008,7 @@ public static ExpandedNodeId ToExpandedNodeId(NodeId nodeId, NamespaceTable name
10011008 /// </summary>
10021009 internal void SetNamespaceIndex ( ushort value )
10031010 {
1011+ ValidateImmutableNodeIdIsNotModified ( ) ;
10041012 m_namespaceIndex = value ;
10051013 }
10061014
@@ -1009,6 +1017,7 @@ internal void SetNamespaceIndex(ushort value)
10091017 /// </summary>
10101018 internal void SetIdentifier ( IdType idType , object value )
10111019 {
1020+ ValidateImmutableNodeIdIsNotModified ( ) ;
10121021 m_identifierType = idType ;
10131022
10141023 switch ( idType )
@@ -1038,6 +1047,8 @@ internal void SetIdentifier(IdType idType, object value)
10381047 /// </summary>
10391048 internal void SetIdentifier ( string value , IdType idType )
10401049 {
1050+ ValidateImmutableNodeIdIsNotModified ( ) ;
1051+
10411052 m_identifierType = idType ;
10421053 SetIdentifier ( IdType . String , value ) ;
10431054 }
@@ -1495,6 +1506,8 @@ internal string IdentifierText
14951506 }
14961507 set
14971508 {
1509+ ValidateImmutableNodeIdIsNotModified ( ) ;
1510+
14981511 NodeId nodeId = NodeId . Parse ( value ) ;
14991512
15001513 m_namespaceIndex = nodeId . NamespaceIndex ;
@@ -1859,6 +1872,21 @@ private static void FormatIdentifier(IFormatProvider formatProvider, StringBuild
18591872 }
18601873 }
18611874 }
1875+
1876+ /// <summary>
1877+ /// Validate that an immutable NodeId is not overwritten.
1878+ /// </summary>
1879+ /// <exception cref="InvalidOperationException"></exception>
1880+ [ Conditional ( "IMMUTABLENULLNODEID" ) ]
1881+ private void ValidateImmutableNodeIdIsNotModified ( )
1882+ {
1883+ #if IMMUTABLENULLNODEID
1884+ if ( this is ImmutableNodeId )
1885+ {
1886+ throw new InvalidOperationException ( "Cannot modify the immutable NodeId.Null." ) ;
1887+ }
1888+ #endif
1889+ }
18621890 #endregion
18631891
18641892 #region Private Fields
@@ -1868,6 +1896,20 @@ private static void FormatIdentifier(IFormatProvider formatProvider, StringBuild
18681896 #endregion
18691897 }
18701898
1899+ #if IMMUTABLENULLNODEID
1900+ #region ImmutableNodeId
1901+ /// <summary>
1902+ /// A NodeId class as helper to catch if the immutable NodeId.Null is being modified.
1903+ /// </summary>
1904+ internal class ImmutableNodeId : NodeId
1905+ {
1906+ internal ImmutableNodeId ( )
1907+ {
1908+ }
1909+ }
1910+ #endregion
1911+ #endif
1912+
18711913 #region NodeIdCollection Class
18721914 /// <summary>
18731915 /// A collection of NodeIds.
@@ -1993,6 +2035,7 @@ public class NodeIdParsingOptions
19932035 /// </summary>
19942036 public ushort [ ] ServerMappings { get ; set ; }
19952037 }
2038+
19962039 #region NodeIdComparer Class
19972040 /// <summary>
19982041 /// Helper which implements a NodeId IEqualityComparer for Linq queries.
0 commit comments