This tutorial shows how to create and use the choice types in a simple program. The program can be compiled using the Cω compiler.
To run this tutorial, you may use the following project and source files:
These files are located in the \samples\Basics\Address subdirectory under the path where you installed Cω, which by default is C:\Program Files\Comega.
XSD content models also allow the use of choice elements <choice>,
or | in DTDs. In Cω we can express these using choice types.
For example, we can use a choice type to define an Address
that allows either a Street or a POBox:
struct Address {
struct{
choice { string Street; int POBox; };
string City;
int? ZipCode;
string Country;
};
}
The type choice{ string Street; int POBox; } captures
the fact that an Address can either contain a string Street;
or an int POBox; member, but not both.
Member access over choice types gives rise to an interesting question about the
result type. Given an instance of type Address, what
should the types be for accessing a.POBox and
a.Street be? Since an instance a of type Address
can either contain a Street member of type string
or a POBox member of type int,
accessing a.Street will either return a string
when a does contain a Street member,
or null when a does not contain
a Street member and similarly, when a contains
a POBox member, accessing a.POBox
returns an int, and when a does not
contain a POBox member, it returns null.
Optional types solve this dilemma: the type of a.Street
becomes string?, and the type of a.POBox
becomes int?.
Now what should be the result type of the query a.* that
selects all the members of the instance a of type
Address. Wild-card selection a.* is
shorthand for the following generator expression:
{ yield return a.Street; yield return a.POBox ; yield return a.City; yield return a.ZipCode; yield return a.Country; }
that yields the stream "One Microsoft Way", "Redmond", 98052, "US",
provided we are using it to yield a business street address for Microsoft. The
returned stream elements are either of type string or of type integer, and any
nulls are discarded. In Cω, the result type is thus a stream containing
strings and integers choice{int;string;}*.
The following is a complete Cω program that demonstrates using the choice types of Cω as discussed above.
using System;
using System.IO;
using Microsoft.Comega;
struct Address {
struct{
choice { string Street; int POBox; };
string City;
int? ZipCode;
string Country;
};
}
public class Test {
public static void Main() {
a = <Address>
<Street>One Microsoft Way</Street>
<City>Redmond</City>
<Country>USA</Country>
</Address>;
// get Street
string? b = a.Street;
foreach(it in b){ Console.WriteLine("Street = {0}", it); };
//get POBox
int? c = a.POBox;
foreach(it in c){ Console.WriteLine("POBox = {0}", it); };
// Serialize whole thing
StringWriter sw = new StringWriter();
new XmlSerializer(typeof(Address)).Serialize(sw,a);
Console.WriteLine(sw.ToString());
System.Console.ReadLine();
}
}
Street = One Microsoft Way <Address> <Street>One Microsoft Way</Street> <City>Redmond</City> <Country>USA</Country> </Address>