In the following example, the value for parameter a of the MyAttributeAttribute constructor is erroneously passed the value of the second parameter, b:
namespace MyNamespace
{
static
{
public static void Main()
{
for (let type in Type.Types)
{
if (let myAttribute = type.GetCustomAttribute<MyAttributeAttribute>())
{
// Prints "A = 2, B = 2" despite (1, 2) being passed to the attribute
Console.WriteLine(scope $"A = {myAttribute.a}, B = {myAttribute.b}");
}
}
}
}
[AttributeUsage(.Struct, .AlwaysIncludeTarget | .ReflectAttribute, AlwaysIncludeUser = .All)]
public struct MyAttributeAttribute : Attribute
{
public uint32 a;
public uint32 b;
internal this(uint32 a, uint32 b)
{
this.a = a;
this.b = b;
}
}
[MyAttribute(1, 2)]
public struct MyStruct
{
}
}
There are additional permutations in which this issue arises. For example, if b is removed, but the parameter for b remains, a is still passed b's value:
namespace MyNamespace
{
static
{
public static void Main()
{
for (let type in Type.Types)
{
if (let myAttribute = type.GetCustomAttribute<MyAttributeAttribute>())
{
// Prints "A = 2"
Console.WriteLine(scope $"A = {myAttribute.a}");
}
}
}
}
[AttributeUsage(.Struct, .AlwaysIncludeTarget | .ReflectAttribute, AlwaysIncludeUser = .All)]
public struct MyAttributeAttribute : Attribute
{
public uint32 a;
internal this(uint32 a, uint32 b)
{
this.a = a;
}
}
[MyAttribute(1, 2)]
public struct MyStruct
{
}
}
More generally, all attribute parameters seem to be assigned the value of the last parameter:
[AttributeUsage(.Struct, .AlwaysIncludeTarget | .ReflectAttribute, AlwaysIncludeUser = .All)]
public struct MyAttributeAttribute : Attribute
{
public uint32 a;
public uint32 b;
internal this(uint32 a, uint32 b, uint32 c)
{
// Both parameter values here are 3
this.a = a;
this.b = b;
}
}
[MyAttribute(1, 2, 3)]
public struct MyStruct
{
}
Finally, the issue appears to be related to unsigned primitives (although I haven't exhaustively tested all relevant permutations, primitives or otherwise). In the examples above, using int32 rather than uint32 fixes the problem. Using a different unsigned type (say, uint16) manifests the problem.
In the following example, the value for parameter
a
of theMyAttributeAttribute
constructor is erroneously passed the value of the second parameter,b
:There are additional permutations in which this issue arises. For example, if
b
is removed, but the parameter forb
remains,a
is still passedb
's value:More generally, all attribute parameters seem to be assigned the value of the last parameter:
Finally, the issue appears to be related to unsigned primitives (although I haven't exhaustively tested all relevant permutations, primitives or otherwise). In the examples above, using
int32
rather thanuint32
fixes the problem. Using a different unsigned type (say,uint16
) manifests the problem.