Here is how our simple string component looks in C#:
Listing 5. Component in C# (CompCS.cs)
using System; namespace CompCS { public class StringComponent { private string[] StringsSet; public StringComponent() { StringsSet = new string[] { "C# String 0", "C# String 1", "C# String 2", "C# String 3" }; } public string GetString(int index) { if ((index < 0) || (index >= Count)) { throw new IndexOutOfRangeException(); } return StringsSet[index]; } public int Count { get { return StringsSet.Count; } } } }
As mentioned above, we use the namespace
statement to create a new namespace to encapsulate the classes we will be creating:
namespace CompCS {…}
This namespace may be nested and may be split between multiple files: A single source code file may also contain multiple non-nested namespaces. A containing namespace is required, since all C# code must be contained in a class.
public class StringComponent {…}
This statement means that instances of StringComponent
will now be created by the runtime and managed in the Garbage Collected heap. The class constructor – which executes each time a new instance of the class is created – has the same name as the class and doesn't have a return type.
public StringComponent() {…}
Since C# uses only managed types, we don't have to do anything special – as we had to do with managed C++ - when declaring variables.
Here's the GetString
method, which takes an integer and returns a string:
public string GetString(int index) { … return StringsSet[index]; }
Note the throw
statement in the GetString
method:
throw new IndexOutOfRangeException();
This statement creates – and throws – a runtime-based exception handling object of type IndexOutOfRangeException
.
Another way of returning strings would be to use an indexer instead of the GetString
method:
public string this[int index] { if ((index < 0) || (index >= Count)) { throw new IndexOutOfRangeException(); } return StringsSet[index]; }
An indexer would allow the client to use a much more natural syntax of:
StringSetVar[index]
VB, however, doesn't support indexers so, in the interest of keeping the component code the space for each of the three languages, we have chosen to use a distinct GetString
method.
Finally, we create the read-only property Count
:
public int Count { get { return StringsSet.Count; } }
The compile process for a C# component is only a little more complicated than for a stand-alone program:
csc /out:..\Bin\CompCS.dll /target:library CompCS.cs
As with the C++ component, we use the /out
switch to put the compiled component in the "..\Bin" relative subdirectory for convenience. Likewise, we need the /target:library
switch to actually create a DLL rather than an executable with a .dll file extension.