I am desperately trying to build a generic union type with explicit field
layout. First, I will show you my attempt without generics. This is something
like a tagged union in functional languages like F#. Thus let us first write
an example using F#, which is rather short (assuming polymorphic types 'T
stack and 'T queue already defined)
---
type 'T ProcessingOrder = Stack of 'T stack | Queue of 'T queue;;
---
This defines the generic type ProcessingOrder to be either a stack or a
queue, with explicit tags Stack and Queue. 'T is the type parameter. As I
have found out using IL DASM, F# circumvents my problem by using auto layout
and thus does not create a real union type, wasting space.
Let me define the same type using C#:
---
[StructLayout(LayoutKind.Explicit)]
struct ProcessingOrder<T>
{
[FieldOffset(0)] public readonly object _object;
[FieldOffset(0)] public Stack<T> _stack;
[FieldOffset(0)] public Queue<T> _queue;
}
---
Note that I use implicit tagging, as classes in .NET are already tagged. One
may explore the actual type of the union by typeof(_object). Propably not the
fastest way.
Unfortunately, this does not work. Compiles without error messages but at
execution a TypeLoadException is thrown, which tells me that explicit layout
is not allowed for generic types.
Au contraire, a specialized implementation works fine:
---
[StructLayout(LayoutKind.Explicit)]
struct ProcessingOrderInt
{
[FieldOffset(0)] public readonly object _object;
[FieldOffset(0)] public Stack<int> _stack;
[FieldOffset(0)] public Queue<int> _queue;
}
---
Has anyone an idea why explicit layout is forbidden for generic types? Has
anyone an idea how to circumvent this without accouting space for every
choice?

TIA,
Hagen

Re: Generic Union Type with Explicit Layout by Mattias

Mattias
Tue Nov 29 12:43:52 CST 2005


>Note that I use implicit tagging, as classes in .NET are already tagged. One
>may explore the actual type of the union by typeof(_object). Propably not the
>fastest way.

I don't see why you need the _stack and _queue fields at all if you
still are going to work with the Object field _object. Can't you just
do something like

class ProcessingOrder<T>
{
private object _object;

public Stack<T> Stack { get { return (Stack<T>)_object; } }
public Queue<T> Queue { get { return (Queue<T>)_object; } }
public bool IsQueue { get { return _object is Queue<T>; } }
}


Mattias

--
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.

Re: Generic Union Type with Explicit Layout by HagenSchendel

HagenSchendel
Wed Nov 30 04:29:07 CST 2005

Thanks for pointing that out, Mattias! Very helpful! Class casting and
properties already provide everything necessary for a tagged union type. What
I want is maximum type safety. By making _object private and using properties
I get what I intended.

---
class ProcessingOrder<T>
{
private object _object;

public Stack<T> Stack
{
set { _object = value; }
get { return (Stack<T>) _object; }
}

public Queue<T> Queue
{
set { _object = value; }
get { return (Queue<T>) _object; }
}

public object Object { get { return _object; } }

public ProcessingOrder (Stack<T> toStack) { Stack = toStack; }
public ProcessingOrder(Queue<T> toQueue) { Queue = toQueue; }
}
---

Now one would store stacks or queues using something like
---
ProcessingOrder<int> po;
po.Stack = new Stack<int> ();
---
To match a choice, I use "is" on the Object property:
---
if(po.Object is Stack<int>) ...
else ...
---

Re: Generic Union Type with Explicit Layout by HagenSchendel

HagenSchendel
Wed Nov 30 05:30:02 CST 2005

There is an error in my previous solution. You need to assign _object
explcitely in the constructors. Thus my solution is:

---
class ProcessingOrder<T>
{
private object _object;

public Stack<T> Stack
{
set { _object = value; }
get { return (Stack<T>) _object; }
}

public Queue<T> Queue
{
set { _object = value; }
get { return (Queue<T>) _object; }
}

public object Object { get { return _object; } }

public ProcessingOrder (Stack<T> toStack) { _object = toStack; }
public ProcessingOrder(Queue<T> toQueue) { _object = toQueue; }
}
---

Re: Generic Union Type with Explicit Layout by Lloyd

Lloyd
Wed Nov 30 07:05:44 CST 2005

BTW, you can't make union of managed/reference type.

thus the following is authorized:
[StructLayout(LayoutKind.Explicit)]
struct ProcessingOrder<T>
{
[FieldOffset(0)] public int AnInt;
[FieldOffset(0)] public double ADouble;
[FieldOffset(0)] public DateTime ATime;
}

while this is not
[StructLayout(LayoutKind.Explicit)]
struct ProcessingOrder<T>
{
[FieldOffset(0)] public object AnObject;
[FieldOffset(0)] public Control AControl;
[FieldOffset(0)] public String AString;
}


"Hagen Schendel" <Hagen Schendel@discussions.microsoft.com> wrote in message
news:F00F6F69-62BD-4BE8-826A-741D2B60AB85@microsoft.com...
>I am desperately trying to build a generic union type with explicit field
> layout. First, I will show you my attempt without generics. This is
> something
> like a tagged union in functional languages like F#. Thus let us first
> write
> an example using F#, which is rather short (assuming polymorphic types 'T
> stack and 'T queue already defined)
> ---
> type 'T ProcessingOrder = Stack of 'T stack | Queue of 'T queue;;
> ---
> This defines the generic type ProcessingOrder to be either a stack or a
> queue, with explicit tags Stack and Queue. 'T is the type parameter. As I
> have found out using IL DASM, F# circumvents my problem by using auto
> layout
> and thus does not create a real union type, wasting space.
> Let me define the same type using C#:
> ---
> [StructLayout(LayoutKind.Explicit)]
> struct ProcessingOrder<T>
> {
> [FieldOffset(0)] public readonly object _object;
> [FieldOffset(0)] public Stack<T> _stack;
> [FieldOffset(0)] public Queue<T> _queue;
> }
> ---
> Note that I use implicit tagging, as classes in .NET are already tagged.
> One
> may explore the actual type of the union by typeof(_object). Propably not
> the
> fastest way.
> Unfortunately, this does not work. Compiles without error messages but at
> execution a TypeLoadException is thrown, which tells me that explicit
> layout
> is not allowed for generic types.
> Au contraire, a specialized implementation works fine:
> ---
> [StructLayout(LayoutKind.Explicit)]
> struct ProcessingOrderInt
> {
> [FieldOffset(0)] public readonly object _object;
> [FieldOffset(0)] public Stack<int> _stack;
> [FieldOffset(0)] public Queue<int> _queue;
> }
> ---
> Has anyone an idea why explicit layout is forbidden for generic types? Has
> anyone an idea how to circumvent this without accouting space for every
> choice?
>
> TIA,
> Hagen