C# Language Unions de style C en C #


Exemple

Les types d'union sont utilisés dans plusieurs langues, comme le langage C, pour contenir plusieurs types différents qui peuvent "se chevaucher". En d'autres termes, ils peuvent contenir des champs différents qui démarrent tous au même décalage de mémoire, même s'ils peuvent avoir des longueurs et des types différents. Cela a l'avantage d'économiser de la mémoire et d'effectuer une conversion automatique. Pensez à une adresse IP, par exemple. En interne, une adresse IP est représentée sous forme d'entier, mais nous souhaitons parfois accéder au composant Byte différent, comme dans Byte1.Byte2.Byte3.Byte4. Cela fonctionne pour tous les types de valeur, que ce soit des primitives comme Int32 ou long, ou pour d'autres structures que vous définissez vous-même.

Nous pouvons obtenir le même effet en C # en utilisant des structures de disposition explicites.

using System;
using System.Runtime.InteropServices;

// The struct needs to be annotated as "Explicit Layout"
[StructLayout(LayoutKind.Explicit)]
struct IpAddress
{
    // The "FieldOffset" means that this Integer starts, an offset in bytes.
    // sizeof(int) 4, sizeof(byte) = 1
    [FieldOffset(0)] public int Address;
    [FieldOffset(0)] public byte Byte1;
    [FieldOffset(1)] public byte Byte2;
    [FieldOffset(2)] public byte Byte3;
    [FieldOffset(3)] public byte Byte4;

    public IpAddress(int address) : this()
    {
        // When we init the Int, the Bytes will change too.
        Address = address;
    }

    // Now we can use the explicit layout to access the 
    // bytes separately, without doing any conversion.
    public override string ToString() => $"{Byte1}.{Byte2}.{Byte3}.{Byte4}";
}

Ayant défini Struct de cette manière, nous pouvons l’utiliser comme nous utiliserions une Union en C. Par exemple, créons une adresse IP en tant qu’entier aléatoire, puis modifions le premier jeton de l’adresse en «100», en le modifiant. de 'ABCD' à '100.BCD':

var ip = new IpAddress(new Random().Next());
Console.WriteLine($"{ip} = {ip.Address}");
ip.Byte1 = 100;
Console.WriteLine($"{ip} = {ip.Address}");

Sortie:

75.49.5.32 = 537211211
100.49.5.32 = 537211236

Voir la démo