77using System . Linq ;
88using System . Numerics ;
99
10- using AttrKVP = System . Collections . Generic . KeyValuePair < string , object > ;
10+ using AttrKVP = System . Collections . Generic . KeyValuePair < string , object ? > ;
1111using System . Reflection ;
1212using System . IO ;
1313
@@ -18,7 +18,7 @@ namespace Datamodel
1818 /// </summary>
1919 [ DebuggerTypeProxy ( typeof ( DebugView ) ) ]
2020 [ DebuggerDisplay ( "Count = {Count}" ) ]
21- public class AttributeList : IDictionary < string , object > , IDictionary
21+ public class AttributeList : IDictionary < string , object ? > , IDictionary
2222 {
2323 internal OrderedDictionary PropertyInfos ;
2424 internal OrderedDictionary Inner ;
@@ -29,6 +29,11 @@ private ICollection<Attribute> GetPropertyBasedAttributes(bool useSerializationN
2929 var result = new List < Attribute > ( ) ;
3030 foreach ( DictionaryEntry entry in PropertyInfos )
3131 {
32+ if ( entry . Value is null )
33+ {
34+ throw new InvalidDataException ( "Property value can not be null" ) ;
35+ }
36+
3237 var prop = ( PropertyInfo ) entry . Value ;
3338 var name = useSerializationName ? ( string ) entry . Key : prop . Name ;
3439 var attr = new Attribute ( name , this , prop . GetValue ( this ) ) ;
@@ -64,7 +69,7 @@ public DebugAttribute(Attribute attr)
6469 readonly Attribute Attr ;
6570
6671 [ DebuggerBrowsable ( DebuggerBrowsableState . RootHidden ) ]
67- object Value { get { return Attr . Value ; } }
72+ object ? Value { get { return Attr . Value ; } }
6873 }
6974 }
7075
@@ -109,7 +114,7 @@ public AttributeList(Datamodel? owner)
109114 /// </summary>
110115 /// <param name="key">The name of the attribute. Must be unique to this AttributeList.</param>
111116 /// <param name="value">The value of the Attribute. Must be of a valid Datamodel type.</param>
112- public void Add ( string key , object value )
117+ public void Add ( string key , object ? value )
113118 {
114119 this [ key ] = value ;
115120 }
@@ -128,7 +133,14 @@ public void Add(string key, object value)
128133 /// <exception cref="KeyNotFoundException">Thrown when the given attribute is not present in the list.</exception>
129134 public OverrideType ? GetOverrideType ( string key )
130135 {
131- return ( ( Attribute ) Inner [ key ] ) . OverrideType ;
136+ var attrib = Inner [ key ] ;
137+
138+ if ( attrib is null )
139+ {
140+ return null ;
141+ }
142+
143+ return ( ( Attribute ) attrib ) . OverrideType ;
132144 }
133145
134146 /// <summary>
@@ -139,7 +151,13 @@ public void Add(string key, object value)
139151 /// <exception cref="AttributeTypeException">Thrown when the attribute's CLR type does not map to the value given in <paramref name="type"/>.</exception>
140152 public void SetOverrideType ( string key , OverrideType ? type )
141153 {
142- ( ( Attribute ) Inner [ key ] ) . OverrideType = type ;
154+ var attrib = Inner [ key ] ;
155+
156+ if ( attrib is not null )
157+ {
158+ ( ( Attribute ) attrib ) . OverrideType = type ;
159+ }
160+
143161 }
144162
145163 /// <summary>
@@ -162,7 +180,7 @@ public bool Remove(string key)
162180 {
163181 lock ( Attribute_ChangeLock )
164182 {
165- var attr = ( Attribute ) Inner [ key ] ;
183+ var attr = ( Attribute ? ) Inner [ key ] ;
166184 if ( attr == null ) return false ;
167185
168186 var index = IndexOf ( key ) ;
@@ -172,11 +190,11 @@ public bool Remove(string key)
172190 }
173191 }
174192
175- public bool TryGetValue ( string key , out object value )
193+ public bool TryGetValue ( string key , out object ? value )
176194 {
177- Attribute result ;
195+ Attribute ? result ;
178196 lock ( Attribute_ChangeLock )
179- result = ( Attribute ) Inner [ key ] ;
197+ result = ( Attribute ? ) Inner [ key ] ;
180198
181199 if ( result != null )
182200 {
@@ -200,7 +218,7 @@ public ICollection<string> Keys
200218 {
201219 get { lock ( Attribute_ChangeLock ) return Inner . Keys . Cast < string > ( ) . ToArray ( ) ; }
202220 }
203- public ICollection < object > Values
221+ public ICollection < object ? > Values
204222 {
205223 get { lock ( Attribute_ChangeLock ) return Inner . Values . Cast < Attribute > ( ) . Select ( attr => attr . Value ) . ToArray ( ) ; }
206224 }
@@ -223,7 +241,7 @@ public virtual object? this[string name]
223241 var attr = ( Attribute ? ) Inner [ name ] ;
224242 if ( attr == null )
225243 {
226- var prop_attr = ( PropertyInfo ) PropertyInfos [ name ] ;
244+ var prop_attr = ( PropertyInfo ? ) PropertyInfos [ name ] ;
227245 if ( prop_attr != null )
228246 {
229247 return prop_attr . GetValue ( this ) ;
@@ -238,16 +256,16 @@ public virtual object? this[string name]
238256 {
239257 ArgumentNullException . ThrowIfNull ( name ) ;
240258 if ( value != null && ! Datamodel . IsDatamodelType ( value . GetType ( ) ) )
241- throw new AttributeTypeException ( String . Format ( "{0 } is not a valid Datamodel attribute type. (If this is an array, it must implement IList<T>).", value . GetType ( ) . FullName ) ) ;
259+ throw new AttributeTypeException ( $ " { value . GetType ( ) . FullName } is not a valid Datamodel attribute type. (If this is an array, it must implement IList<T>).") ;
242260
243- if ( Owner != null && this == Owner . PrefixAttributes && value . GetType ( ) == typeof ( Element ) )
261+ if ( Owner != null && this == Owner . PrefixAttributes && value ? . GetType ( ) == typeof ( Element ) )
244262 throw new AttributeTypeException ( "Elements are not supported as prefix attributes." ) ;
245263
246- var prop_attr = ( PropertyInfo ) PropertyInfos [ name ] ;
264+ var prop_attr = ( PropertyInfo ? ) PropertyInfos [ name ] ;
247265
248266 if ( prop_attr != null )
249267 {
250- PropertyInfo prop = GetType ( ) . GetProperty ( prop_attr . Name , BindingFlags . Public | BindingFlags . Instance ) ;
268+ PropertyInfo ? prop = GetType ( ) . GetProperty ( prop_attr . Name , BindingFlags . Public | BindingFlags . Instance ) ;
251269
252270 if ( prop != null && prop . CanWrite )
253271 {
@@ -272,12 +290,12 @@ public virtual object? this[string name]
272290 return ;
273291 }
274292
275- Attribute old_attr ;
276- Attribute new_attr ;
293+ Attribute ? old_attr ;
294+ Attribute ? new_attr ;
277295 int old_index = - 1 ;
278296 lock ( Attribute_ChangeLock )
279297 {
280- old_attr = ( Attribute ) Inner [ name ] ;
298+ old_attr = ( Attribute ? ) Inner [ name ] ;
281299 new_attr = new Attribute ( name , this , value ) ;
282300
283301 if ( old_attr != null )
@@ -305,7 +323,13 @@ public AttrKVP this[int index]
305323 {
306324 get
307325 {
308- var attr = ( Attribute ) Inner [ index ] ;
326+ var attr = ( Attribute ? ) Inner [ index ] ;
327+
328+ if ( attr is null )
329+ {
330+ throw new InvalidOperationException ( $ "attribute at index { index } doesn't exist") ;
331+ }
332+
309333 return attr . ToKeyValuePair ( ) ;
310334 }
311335 set
@@ -320,12 +344,16 @@ public AttrKVP this[int index]
320344 /// </summary>
321345 public void RemoveAt ( int index )
322346 {
323- Attribute attr ;
347+ Attribute ? attr ;
324348 lock ( Attribute_ChangeLock )
325349 {
326- attr = ( Attribute ) Inner [ index ] ;
327- attr . Owner = null ;
328- Inner . RemoveAt ( index ) ;
350+ attr = ( Attribute ? ) Inner [ index ] ;
351+
352+ if ( attr is not null )
353+ {
354+ attr . Owner = null ;
355+ Inner . RemoveAt ( index ) ;
356+ }
329357 }
330358 OnCollectionChanged ( new NotifyCollectionChangedEventArgs ( NotifyCollectionChangedAction . Remove , attr , index ) ) ;
331359 }
@@ -398,7 +426,7 @@ IEnumerator IEnumerable.GetEnumerator()
398426 /// Raised when <see cref="Element.Name"/>, <see cref="Element.ClassName"/>, <see cref="Element.ID"/> or
399427 /// a custom Element property has changed.
400428 /// </summary>
401- public event PropertyChangedEventHandler PropertyChanged ;
429+ public event PropertyChangedEventHandler ? PropertyChanged ;
402430 protected virtual void OnPropertyChanged ( [ System . Runtime . CompilerServices . CallerMemberName ( ) ] string property = "" )
403431 {
404432 PropertyChanged ? . Invoke ( this , new PropertyChangedEventArgs ( property ) ) ;
@@ -407,7 +435,7 @@ protected virtual void OnPropertyChanged([System.Runtime.CompilerServices.Caller
407435 /// <summary>
408436 /// Raised when an <see cref="Attribute"/> is added, removed, or replaced.
409437 /// </summary>
410- public event NotifyCollectionChangedEventHandler CollectionChanged ;
438+ public event NotifyCollectionChangedEventHandler ? CollectionChanged ;
411439 protected virtual void OnCollectionChanged ( NotifyCollectionChangedEventArgs e )
412440 {
413441 Debug . Assert ( ! ( e . NewItems != null && e . NewItems . OfType < Attribute > ( ) . Any ( ) ) && ! ( e . OldItems != null && e . OldItems . OfType < Attribute > ( ) . Any ( ) ) ) ;
@@ -437,12 +465,12 @@ void IDictionary.Remove(object key)
437465 Remove ( ( string ) key ) ;
438466 }
439467
440- void IDictionary . Add ( object key , object value )
468+ void IDictionary . Add ( object key , object ? value )
441469 {
442470 Add ( ( string ) key , value ) ;
443471 }
444472
445- object IDictionary . this [ object key ]
473+ object ? IDictionary . this [ object key ]
446474 {
447475 get
448476 {
@@ -466,7 +494,7 @@ bool ICollection<AttrKVP>.Remove(AttrKVP item)
466494 {
467495 lock ( Attribute_ChangeLock )
468496 {
469- var attr = ( Attribute ) Inner [ item . Key ] ;
497+ var attr = ( Attribute ? ) Inner [ item . Key ] ;
470498 if ( attr == null || attr . Value != item . Value ) return false ;
471499 Remove ( attr . Name ) ;
472500 return true ;
@@ -497,7 +525,7 @@ bool ICollection<AttrKVP>.Contains(AttrKVP item)
497525 {
498526 lock ( Attribute_ChangeLock )
499527 {
500- var attr = ( Attribute ) Inner [ item . Key ] ;
528+ var attr = ( Attribute ? ) Inner [ item . Key ] ;
501529 return attr != null && attr . Value == item . Value ;
502530 }
503531 }
@@ -521,12 +549,17 @@ public static ValueComparer Default
521549 return _Default ;
522550 }
523551 }
524- static ValueComparer _Default ;
552+ static ValueComparer ? _Default ;
525553
526- public new bool Equals ( object x , object y )
554+ public new bool Equals ( object ? x , object ? y )
527555 {
528- var type_x = x ? . GetType ( ) ;
529- var type_y = y ? . GetType ( ) ;
556+ if ( x is null || y is null )
557+ {
558+ return false ;
559+ }
560+
561+ var type_x = x . GetType ( ) ;
562+ var type_y = y . GetType ( ) ;
530563
531564 if ( type_x == null && type_y == null )
532565 return true ;
0 commit comments