Voici une tentative pour contenir plusieurs messages complexes (simplifiés ici) dans une Union. Les messages sont mutuellement exclusifs, nous n'en avons qu'un seul disponible à la fois, voire aucun. J'aborde ici la forme conceptuelle de l'union, pas la forme technique (binaire) qui est abordée par d'autres messages dans cette page.
public class Msg1 {
public int v;
}
public class Msg2 {
public double v;
}
public class Msg3 {
public string v;
}
public class Union {
public enum selector_t {
NONE,
MSG1,
MSG2,
MSG3,
}
private selector_t _selector;
private Object _value;
public Union() {
reset();
}
public Union( Msg1 value ) {
set( value );
}
public Union( Msg2 value ) {
set( value );
}
public Union( Msg3 value ) {
set( value );
}
private void set( selector_t selector, Object value ) {
_selector = selector;
_value = value;
}
public selector_t getSelector() {
return _selector;
}
public bool isNone() {
return _selector == selector_t.NONE;
}
public bool isMsg1() {
return _selector == selector_t.MSG1;
}
public bool isMsg2() {
return _selector == selector_t.MSG2;
}
public bool isMsg3() {
return _selector == selector_t.MSG3;
}
public void reset() {
set( selector_t.NONE, null );
}
public void set( Msg1 value ) {
set( selector_t.MSG1, value );
}
public void set( Msg2 value ) {
set( selector_t.MSG2, value );
}
public void set( Msg3 value ) {
set( selector_t.MSG3, value );
}
public Msg1 getMsg1() {
return (Msg1)_value;
}
public Msg2 getMsg2() {
return (Msg2)_value;
}
public Msg3 getMsg3() {
return (Msg3)_value;
}
}
class Program {
static void Main(string[] args) {
Union u = new Union( new Msg2());
Console.WriteLine( "isMsg1: " + u.isMsg1());
Console.WriteLine( "isMsg2: " + u.isMsg2());
Console.WriteLine( "isMsg3: " + u.isMsg3());
Console.WriteLine( "getMsg2: " + u.getMsg2());
try {
Console.WriteLine( "getMsg3: " + u.getMsg3());
}
catch( InvalidCastException x ) {
Console.WriteLine(x);
}
u.set( new Msg3());
try {
Console.WriteLine( "getMsg3: " + u.getMsg3());
}
catch( InvalidCastException x ) {
Console.WriteLine(x);
}
}
}
Journal d'exécution :
isMsg1: False
isMsg2: True
isMsg3: False
getMsg2: Union.Msg2
System.InvalidCastException: Impossible d'effectuer un cast d'un objet de type 'Union.Msg2' en type 'Union.Msg3'.
à Union.Union.getMsg3() dans f:\dev\C#\2014\Union\Program.cs:ligne 99
à Union.Program.Main(String[] args) dans f:\dev\C#\2014\Union\Program.cs:ligne 111
getMsg3: Union.Msg3
El System.InvalidCastException
est attendu, car nous tentons d'utiliser un Msg2
como Msg3
.
0 votes
C'est peut-être plus sûr, mais lorsque vous interagissez avec des bibliothèques C qui fournissent ces types de structures de données, cette décision en C# brise même l'encapsulation rudimentaire de vos structures C/C++. J'essaie de traiter quelque chose comme ceci : struct LibrarySType { AnotherType *anotherTypeBuff ; int oneSetOfFlags ; int anotherSetOfFlags ; union { struct { int structMember1 ; ... } oneUseOfThisLibraryType ; struct { char *structMember2 ; ... } anotherUseOfThisLibraryType ; ... } u ; int64 *moreStuff ; ... vous voyez l'idée } Je n'ai pas inventé cette structure de données intelligente, mais elle fait partie de l'API d'un fournisseur dont j'ai besoin.