@@ -16,6 +16,21 @@ namespace Microsoft.Macios.Generator.Attributes;
1616/// <typeparam name="T">The configuration flags used on the exported element.</typeparam>
1717readonly struct ExportData < T > : IEquatable < ExportData < T > > where T : Enum {
1818
19+ /// <summary>
20+ /// The initialization state of the struct.
21+ /// </summary>
22+ StructState State { get ; init ; } = StructState . Default ;
23+
24+ /// <summary>
25+ /// Gets the default, uninitialized instance of <see cref="ExportData{T}"/>.
26+ /// </summary>
27+ public static ExportData < T > Default { get ; } = new ( StructState . Default ) ;
28+
29+ /// <summary>
30+ /// Gets a value indicating whether the instance is the default, uninitialized instance.
31+ /// </summary>
32+ public bool IsNullOrDefault => State == StructState . Default ;
33+
1934 /// <summary>
2035 /// The exported native selector.
2136 /// </summary>
@@ -24,7 +39,7 @@ namespace Microsoft.Macios.Generator.Attributes;
2439 /// <summary>
2540 /// The configuration flags used on the exported member.
2641 /// </summary>
27- public T ? Flags { get ; init ; }
42+ public T Flags { get ; init ; }
2843
2944 /// <summary>
3045 /// Argument semantics to use with the selector.
@@ -90,20 +105,50 @@ namespace Microsoft.Macios.Generator.Attributes;
90105 /// </summary>
91106 public TypeInfo StrongDictionaryKeyClass { get ; init ; } = TypeInfo . Default ;
92107
93- public ExportData ( ) { }
108+ /// <summary>
109+ /// Initializes a new instance of the <see cref="ExportData{T}"/> struct.
110+ /// </summary>
111+ public ExportData ( ) : this ( StructState . Initialized ) { }
94112
95- public ExportData ( string ? selector )
113+ /// <summary>
114+ /// Initializes a new instance of the <see cref="ExportData{T}"/> struct.
115+ /// </summary>
116+ /// <param name="state">The initialization state.</param>
117+ public ExportData ( StructState state )
118+ {
119+ State = state ;
120+ Flags = default ! ;
121+ }
122+
123+ /// <summary>
124+ /// Initializes a new instance of the <see cref="ExportData{T}"/> struct.
125+ /// </summary>
126+ /// <param name="selector">The exported native selector.</param>
127+ public ExportData ( string ? selector ) : this ( StructState . Initialized )
96128 {
97129 Selector = selector ;
130+ Flags = default ! ;
98131 }
99132
100- public ExportData ( string ? selector , ArgumentSemantic argumentSemantic )
133+ /// <summary>
134+ /// Initializes a new instance of the <see cref="ExportData{T}"/> struct.
135+ /// </summary>
136+ /// <param name="selector">The exported native selector.</param>
137+ /// <param name="argumentSemantic">Argument semantics to use with the selector.</param>
138+ public ExportData ( string ? selector , ArgumentSemantic argumentSemantic ) : this ( StructState . Initialized )
101139 {
102140 Selector = selector ;
103141 ArgumentSemantic = argumentSemantic ;
142+ Flags = default ! ;
104143 }
105144
106- public ExportData ( string ? selector , ArgumentSemantic argumentSemantic , T flags )
145+ /// <summary>
146+ /// Initializes a new instance of the <see cref="ExportData{T}"/> struct.
147+ /// </summary>
148+ /// <param name="selector">The exported native selector.</param>
149+ /// <param name="argumentSemantic">Argument semantics to use with the selector.</param>
150+ /// <param name="flags">The configuration flags used on the exported member.</param>
151+ public ExportData ( string ? selector , ArgumentSemantic argumentSemantic , T flags ) : this ( StructState . Initialized )
107152 {
108153 Selector = selector ;
109154 ArgumentSemantic = argumentSemantic ;
@@ -121,7 +166,7 @@ public static bool TryParse (AttributeData attributeData,
121166 {
122167 data = null ;
123168 var count = attributeData . ConstructorArguments . Length ;
124- string ? selector = null ;
169+ string ? selector ;
125170 ArgumentSemantic argumentSemantic = ArgumentSemantic . None ;
126171 T ? flags = default ;
127172
@@ -281,6 +326,8 @@ public static bool TryParse (AttributeData attributeData,
281326 /// <inheritdoc />
282327 public bool Equals ( ExportData < T > other )
283328 {
329+ if ( State == StructState . Default && other . State == StructState . Default )
330+ return true ;
284331 if ( Selector != other . Selector )
285332 return false ;
286333 if ( ArgumentSemantic != other . ArgumentSemantic )
@@ -305,7 +352,7 @@ public bool Equals (ExportData<T> other)
305352 ( null , null ) => true ,
306353 ( null , _ ) => false ,
307354 ( _, null ) => false ,
308- ( _, _) => Flags ! . Equals ( other . Flags )
355+ ( _, _) => Flags . Equals ( other . Flags )
309356 } ;
310357 }
311358
@@ -321,11 +368,23 @@ public override int GetHashCode ()
321368 return HashCode . Combine ( Selector , Flags ) ;
322369 }
323370
371+ /// <summary>
372+ /// Compares two <see cref="ExportData{T}"/> instances for equality.
373+ /// </summary>
374+ /// <param name="x">The first instance.</param>
375+ /// <param name="y">The second instance.</param>
376+ /// <returns><c>true</c> if the instances are equal, <c>false</c> otherwise.</returns>
324377 public static bool operator == ( ExportData < T > x , ExportData < T > y )
325378 {
326379 return x . Equals ( y ) ;
327380 }
328381
382+ /// <summary>
383+ /// Compares two <see cref="ExportData{T}"/> instances for inequality.
384+ /// </summary>
385+ /// <param name="x">The first instance.</param>
386+ /// <param name="y">The second instance.</param>
387+ /// <returns><c>true</c> if the instances are not equal, <c>false</c> otherwise.</returns>
329388 public static bool operator != ( ExportData < T > x , ExportData < T > y )
330389 {
331390 return ! ( x == y ) ;
0 commit comments