Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -897,6 +897,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\IsUnmanagedAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\IteratorStateMachineAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\ITuple.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\IUnion.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\LoadHint.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\MemorySafetyRulesAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\MethodCodeType.cs" />
Expand Down Expand Up @@ -938,6 +939,7 @@
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\UnsafeAccessorAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\UnsafeAccessorTypeAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\UnsafeValueTypeAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\UnionAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\ValueTaskAwaiter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\YieldAwaitable.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\ConstrainedExecution\Cer.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System.Runtime.CompilerServices
{
/// <summary>
/// Provides a common interface for accessing the contents of a union type at runtime.
/// </summary>
/// <remarks>
/// <para>
/// The C# compiler automatically implements this interface on types generated by union declarations.
/// User-defined types annotated with <see cref="UnionAttribute" /> may also implement this interface
/// to provide runtime access to the union's value. Implementing this interface is not required
/// for union behaviors provided by the compiler.
/// </para>
Comment thread
eiriktsarpalis marked this conversation as resolved.
/// </remarks>
/// <seealso cref="UnionAttribute" />
public interface IUnion
{
/// <summary>
/// Gets the value contained in the union, or <see langword="null" /> if the union has no value.
/// </summary>
/// <value>
/// The current value of the union as one of its case types, or <see langword="null" />.
/// </value>
object? Value { get; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System.Runtime.CompilerServices
{
/// <summary>
/// Indicates that a class or struct is a union type, enabling compiler support for union behaviors.
/// </summary>
/// <remarks>
/// <para>
/// Any class or struct annotated with this attribute is recognized by the C# compiler as a union type.
/// Union types may support behaviors such as implicit conversions from case types, pattern matching
/// that unwraps the union's contents, and switch exhaustiveness checking.
/// </para>
/// </remarks>
Comment thread
eiriktsarpalis marked this conversation as resolved.
/// <seealso cref="IUnion" />
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)]
public sealed class UnionAttribute : Attribute
{
}
}
9 changes: 9 additions & 0 deletions src/libraries/System.Runtime/ref/System.Runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14063,6 +14063,10 @@ public partial interface ITuple
object? this[int index] { get; }
int Length { get; }
}
public partial interface IUnion
{
object? Value { get; }
}
Comment thread
eiriktsarpalis marked this conversation as resolved.
public enum LoadHint
{
Default = 0,
Expand Down Expand Up @@ -14489,6 +14493,11 @@ public sealed partial class UnsafeValueTypeAttribute : System.Attribute
{
public UnsafeValueTypeAttribute() { }
}
[System.AttributeUsageAttribute(System.AttributeTargets.Class | System.AttributeTargets.Struct, AllowMultiple=false, Inherited=false)]
public sealed partial class UnionAttribute : System.Attribute
{
public UnionAttribute() { }
}
public readonly partial struct ValueTaskAwaiter : System.Runtime.CompilerServices.ICriticalNotifyCompletion, System.Runtime.CompilerServices.INotifyCompletion
{
private readonly object _dummy;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -426,5 +426,18 @@ public static void OverloadResolutionPriorityAttributeTests()
var attr = new OverloadResolutionPriorityAttribute(42);
Assert.Equal(42, attr.Priority);
}

[Fact]
public static void UnionAttributeTests()
{
var attr = new UnionAttribute();
Assert.NotNull(attr);

var usage = (AttributeUsageAttribute)Attribute.GetCustomAttribute(typeof(UnionAttribute), typeof(AttributeUsageAttribute))!;
Assert.Equal(AttributeTargets.Class | AttributeTargets.Struct, usage.ValidOn);
Assert.False(usage.AllowMultiple);
Comment thread
eiriktsarpalis marked this conversation as resolved.
Comment thread
eiriktsarpalis marked this conversation as resolved.
Assert.False(usage.Inherited);
}

}
}
Loading