Skip to content

Commit e896e52

Browse files
Index.cs: add POLYFILL_NO_INDEX preprocessor guard to avoid duplicate type definitions
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 98eb522 commit e896e52

File tree

1 file changed

+154
-154
lines changed
  • src/PostSharp.Engineering.SystemTypes

1 file changed

+154
-154
lines changed
Lines changed: 154 additions & 154 deletions
Original file line numberDiff line numberDiff line change
@@ -1,155 +1,155 @@
1-
#if !NETCOREAPP && !NETSTANDARD2_1
2-
3-
using System.Runtime.CompilerServices;
4-
using Microsoft.CodeAnalysis;
5-
6-
namespace System
7-
{
8-
/// <summary>Represent a type can be used to index a collection either from the start or the end.</summary>
9-
/// <remarks>
10-
/// Index is used by the C# compiler to support the new index syntax
11-
/// <code>
12-
/// int[] someArray = new int[5] { 1, 2, 3, 4, 5 } ;
13-
/// int lastElement = someArray[^1]; // lastElement = 5
14-
/// </code>
15-
/// </remarks>
16-
#if EMBED_SYSTEM_TYPES
17-
[Embedded]
18-
#endif
19-
internal readonly struct Index : IEquatable<Index>
20-
{
21-
private readonly int _value;
22-
23-
/// <summary>Construct an Index using a value and indicating if the index is from the start or from the end.</summary>
24-
/// <param name="value">The index value. it has to be zero or positive number.</param>
25-
/// <param name="fromEnd">Indicating if the index is from the start or from the end.</param>
26-
/// <remarks>
27-
/// If the Index constructed from the end, index value 1 means pointing at the last element and index value 0 means pointing at beyond last element.
28-
/// </remarks>
29-
[MethodImpl( MethodImplOptions.AggressiveInlining )]
30-
public Index( int value, bool fromEnd = false )
31-
{
32-
if (value < 0)
33-
{
34-
throw new ArgumentOutOfRangeException( nameof(value), value, "Non-negative number required." );
35-
}
36-
37-
if (fromEnd)
38-
{
39-
_value = ~value;
40-
}
41-
else
42-
{
43-
_value = value;
44-
}
45-
}
46-
47-
// The following private constructors mainly created for perf reason to avoid the checks
48-
private Index( int value )
49-
{
50-
_value = value;
51-
}
52-
53-
/// <summary>Create an Index pointing at first element.</summary>
54-
public static Index Start => new( 0 );
55-
56-
/// <summary>Create an Index pointing at beyond last element.</summary>
57-
public static Index End => new( ~0 );
58-
59-
/// <summary>Create an Index from the start at the position indicated by the value.</summary>
60-
/// <param name="value">The index value from the start.</param>
61-
[MethodImpl( MethodImplOptions.AggressiveInlining )]
62-
public static Index FromStart( int value )
63-
{
64-
if (value < 0)
65-
{
66-
throw new ArgumentOutOfRangeException( nameof(value), value, "Non-negative number required." );
67-
}
68-
69-
return new Index( value );
70-
}
71-
72-
/// <summary>Create an Index from the end at the position indicated by the value.</summary>
73-
/// <param name="value">The index value from the end.</param>
74-
[MethodImpl( MethodImplOptions.AggressiveInlining )]
75-
public static Index FromEnd( int value )
76-
{
77-
if (value < 0)
78-
{
79-
throw new ArgumentOutOfRangeException( nameof(value), value, "Non-negative number required." );
80-
}
81-
82-
return new Index( ~value );
83-
}
84-
85-
/// <summary>Returns the index value.</summary>
86-
public int Value
87-
{
88-
get
89-
{
90-
if (_value < 0)
91-
{
92-
return ~_value;
93-
}
94-
else
95-
{
96-
return _value;
97-
}
98-
}
99-
}
100-
101-
/// <summary>Indicates whether the index is from the start or the end.</summary>
102-
public bool IsFromEnd => _value < 0;
103-
104-
/// <summary>Calculate the offset from the start using the giving collection length.</summary>
105-
/// <param name="length">The length of the collection that the Index will be used with. length has to be a positive value</param>
106-
/// <remarks>
107-
/// For performance reason, we don't validate the input length parameter and the returned offset value against negative values.
108-
/// we don't validate either the returned offset is greater than the input length.
109-
/// It is expected Index will be used with collections which always have non negative length/count. If the returned offset is negative and
110-
/// then used to index a collection will get out of range exception which will be same affect as the validation.
111-
/// </remarks>
112-
[MethodImpl( MethodImplOptions.AggressiveInlining )]
113-
public int GetOffset( int length )
114-
{
115-
var offset = _value;
116-
117-
if (IsFromEnd)
118-
{
119-
// offset = length - (~value)
120-
// offset = length + (~(~value) + 1)
121-
// offset = length + value + 1
122-
123-
offset += length + 1;
124-
}
125-
126-
return offset;
127-
}
128-
129-
/// <summary>Indicates whether the current Index object is equal to another object of the same type.</summary>
130-
/// <param name="value">An object to compare with this object</param>
131-
public override bool Equals( object? value ) => value is Index && _value == ( (Index)value )._value;
132-
133-
/// <summary>Indicates whether the current Index object is equal to another Index object.</summary>
134-
/// <param name="other">An object to compare with this object</param>
135-
public bool Equals( Index other ) => _value == other._value;
136-
137-
/// <summary>Returns the hash code for this instance.</summary>
138-
public override int GetHashCode() => _value;
139-
140-
/// <summary>Converts integer number to an Index.</summary>
141-
public static implicit operator Index( int value ) => FromStart( value );
142-
143-
/// <summary>Converts the value of the current Index object to its equivalent string representation.</summary>
144-
public override string ToString()
145-
{
146-
if (IsFromEnd)
147-
{
148-
return $"^{( (uint)Value ).ToString()}";
149-
}
150-
151-
return ( (uint)Value ).ToString();
152-
}
153-
}
154-
}
1+
#if !NETCOREAPP && !NETSTANDARD2_1 && !POLYFILL_NO_INDEX
2+
3+
using System.Runtime.CompilerServices;
4+
using Microsoft.CodeAnalysis;
5+
6+
namespace System
7+
{
8+
/// <summary>Represent a type can be used to index a collection either from the start or the end.</summary>
9+
/// <remarks>
10+
/// Index is used by the C# compiler to support the new index syntax
11+
/// <code>
12+
/// int[] someArray = new int[5] { 1, 2, 3, 4, 5 } ;
13+
/// int lastElement = someArray[^1]; // lastElement = 5
14+
/// </code>
15+
/// </remarks>
16+
#if EMBED_SYSTEM_TYPES
17+
[Embedded]
18+
#endif
19+
internal readonly struct Index : IEquatable<Index>
20+
{
21+
private readonly int _value;
22+
23+
/// <summary>Construct an Index using a value and indicating if the index is from the start or from the end.</summary>
24+
/// <param name="value">The index value. it has to be zero or positive number.</param>
25+
/// <param name="fromEnd">Indicating if the index is from the start or from the end.</param>
26+
/// <remarks>
27+
/// If the Index constructed from the end, index value 1 means pointing at the last element and index value 0 means pointing at beyond last element.
28+
/// </remarks>
29+
[MethodImpl( MethodImplOptions.AggressiveInlining )]
30+
public Index( int value, bool fromEnd = false )
31+
{
32+
if (value < 0)
33+
{
34+
throw new ArgumentOutOfRangeException( nameof(value), value, "Non-negative number required." );
35+
}
36+
37+
if (fromEnd)
38+
{
39+
_value = ~value;
40+
}
41+
else
42+
{
43+
_value = value;
44+
}
45+
}
46+
47+
// The following private constructors mainly created for perf reason to avoid the checks
48+
private Index( int value )
49+
{
50+
_value = value;
51+
}
52+
53+
/// <summary>Create an Index pointing at first element.</summary>
54+
public static Index Start => new( 0 );
55+
56+
/// <summary>Create an Index pointing at beyond last element.</summary>
57+
public static Index End => new( ~0 );
58+
59+
/// <summary>Create an Index from the start at the position indicated by the value.</summary>
60+
/// <param name="value">The index value from the start.</param>
61+
[MethodImpl( MethodImplOptions.AggressiveInlining )]
62+
public static Index FromStart( int value )
63+
{
64+
if (value < 0)
65+
{
66+
throw new ArgumentOutOfRangeException( nameof(value), value, "Non-negative number required." );
67+
}
68+
69+
return new Index( value );
70+
}
71+
72+
/// <summary>Create an Index from the end at the position indicated by the value.</summary>
73+
/// <param name="value">The index value from the end.</param>
74+
[MethodImpl( MethodImplOptions.AggressiveInlining )]
75+
public static Index FromEnd( int value )
76+
{
77+
if (value < 0)
78+
{
79+
throw new ArgumentOutOfRangeException( nameof(value), value, "Non-negative number required." );
80+
}
81+
82+
return new Index( ~value );
83+
}
84+
85+
/// <summary>Returns the index value.</summary>
86+
public int Value
87+
{
88+
get
89+
{
90+
if (_value < 0)
91+
{
92+
return ~_value;
93+
}
94+
else
95+
{
96+
return _value;
97+
}
98+
}
99+
}
100+
101+
/// <summary>Indicates whether the index is from the start or the end.</summary>
102+
public bool IsFromEnd => _value < 0;
103+
104+
/// <summary>Calculate the offset from the start using the giving collection length.</summary>
105+
/// <param name="length">The length of the collection that the Index will be used with. length has to be a positive value</param>
106+
/// <remarks>
107+
/// For performance reason, we don't validate the input length parameter and the returned offset value against negative values.
108+
/// we don't validate either the returned offset is greater than the input length.
109+
/// It is expected Index will be used with collections which always have non negative length/count. If the returned offset is negative and
110+
/// then used to index a collection will get out of range exception which will be same affect as the validation.
111+
/// </remarks>
112+
[MethodImpl( MethodImplOptions.AggressiveInlining )]
113+
public int GetOffset( int length )
114+
{
115+
var offset = _value;
116+
117+
if (IsFromEnd)
118+
{
119+
// offset = length - (~value)
120+
// offset = length + (~(~value) + 1)
121+
// offset = length + value + 1
122+
123+
offset += length + 1;
124+
}
125+
126+
return offset;
127+
}
128+
129+
/// <summary>Indicates whether the current Index object is equal to another object of the same type.</summary>
130+
/// <param name="value">An object to compare with this object</param>
131+
public override bool Equals( object? value ) => value is Index && _value == ( (Index)value )._value;
132+
133+
/// <summary>Indicates whether the current Index object is equal to another Index object.</summary>
134+
/// <param name="other">An object to compare with this object</param>
135+
public bool Equals( Index other ) => _value == other._value;
136+
137+
/// <summary>Returns the hash code for this instance.</summary>
138+
public override int GetHashCode() => _value;
139+
140+
/// <summary>Converts integer number to an Index.</summary>
141+
public static implicit operator Index( int value ) => FromStart( value );
142+
143+
/// <summary>Converts the value of the current Index object to its equivalent string representation.</summary>
144+
public override string ToString()
145+
{
146+
if (IsFromEnd)
147+
{
148+
return $"^{( (uint)Value ).ToString()}";
149+
}
150+
151+
return ( (uint)Value ).ToString();
152+
}
153+
}
154+
}
155155
#endif

0 commit comments

Comments
 (0)