You are on page 1of 14

Sharp New Language: C# Offers the Power of C++ and Simplicity of Visual Basic

Joshua Trupin
This article assumes you're familiar with C++ and COM+

Le el of !ifficulty

"

S%&&'() Many developers wish there was a language that was easy to write, read, and maintain like Visual asic, !ut that still provided the power and fle"i!ility of C++# $or those developers, the new C% language is here# Microsoft has !uilt C% with type&safety, gar!age collection, simplified type declarations, versioning and scala!ility support, and lots of other features that make developing solutions faster and easier, especially for COM+ and 'e! (ervices# This article gives you a first look at C%, a language you are going to !e hearing lots more a!out in the very near future# ou may have read recent press accounts of a new programming language that Microsoft has !een developing# 'ell, the language is here# C%, pronounced )C sharp,) is a new programming language that makes it easier for C and C++ programmers to generate COM+&ready programs# *n addition, C% has !een !uilt from the ground up to make it easier to write and maintain programs# *t's a little like taking all the good stuff in Visual asic+ and adding it to C++, while trimming off some of the more arcane C and C++ traditions# ,oing forward, C% is e"pected to !e the !est language from Microsoft+ for writing COM+ and 'indows+&!ased programs for enterprise computing# -owever, you won't have to migrate your e"isting C or C++ code# *f you like the new features in C%.and you pro!a!ly will.you can migrate your mindset to C%# /et's face it.C++ is a powerful language, !ut it isn't always a walk in the park# *'ve used !oth Visual asic and C++ professionally, and after a while * was asking myself why * needed to implement every last destructor for every last C++ class# C'mon already.you're a smart language# Visual C+++ even has *ntelli(ense+# Clean up after me# *f you like C and C++, !ut sometimes think like * do, C% is for you# The main design goal of C% was simplicity rather than pure power# 0ou do give up a little processing power, !ut you get cool stuff like type safety and automatic gar!age collection in return# C% can make your code more sta!le and productive overall, meaning that you can more than make up that lost power in the long run# C% offers several key !enefits for programmers1

(implicity Consistency Modernity O!2ect&orientation Type&safety (cala!ility Version support Compati!ility $le"i!ility /et's look at each of the ways that C% stands to improve your coding life#

Simplicity 'hat's one of the most annoying things a!out working in C++3 *t's gotta !e remem!ering when to use the &4 pointer indicator, when to use the 11 for a class mem!er, and when to use the dot# 5nd the compiler knows when you get it wrong, doesn't it3 *t even tells you that you got it wrong6 *f there's a reason for that !eyond out&and out taunting, * fail to see it# C% recogni7es this irksome little fi"ture of the C++ programming life and simplifies it# *n C%, everything is represented !y a dot# 'hether you're looking at mem!ers, classes, name&spaces, references, or what have you, you don't need to track which operator to use# Okay, so what's the second most annoying thing a!out working in C and C++3 *t's figuring out e"actly what type of data type to use# *n C%, a 8nicode character is no longer a wchar9t, it's a char# 5 :;&!it

integer is a long, not an 99int:;# 5nd a char is a char is a char# There's no more char, unsigned char, signed char, and wchar9t to track# *'ll talk more a!out data types later in this article# The third most annoying pro!lem that you run across in C and C++ is integers !eing used as ooleans, causing assignment errors when you confuse < and <<# C% separates these two types, providing a separate !ool type that solves this pro!lem# 5 !ool can !e true or false, and can't !e converted into other types# (imilarly, an integer or o!2ect reference can't !e tested to !e true or false.it must !e compared to 7ero =or to null in the case of the reference># *f you wrote code like this in C++1

int i; if (i) . . .

0ou need to convert that into something like this for C%1

int i; if (i != 0) . . .

5nother programmer&friendly feature is the improvement over C++ in the way switch statements work# *n C++, you could write a switch statement that fell through from case to case# $or e"ample, this code

switch (i) { case 1: FunctionA();

case 2: FunctionB(); Break; }

would call !oth $unction5 and $unction if i was e?ual to @# C% works like Visual asic, putting an implied !reak !efore each case statement# *f you really do want the case statement to fall through, you can rewrite the switch !lock like this in C%1

switch (i) { case 1: FunctionA(); goto case 2;

case 2: FunctionB(); Break; }

Consistency C% unifies the type system !y letting you view every type in the language as an o!2ect# 'hether you're using a class, a struct, an array, or a primitive, you'll !e a!le to treat it as an o!2ect# O!2ects are com!ined into namespaces, which allow you to access everything programmatically# This means that instead of putting includes in your file like this

inc!u"e #st"!i$.h% inc!u"e #st"io.h% inc!u"e #string.h%

you include a particular namespace in your program to gain access to the classes and o!2ects contained within it1

using &'ste(;

*n COM+, all classes e"ist within a single hierarchical namespace# *n C%, the using statement lets you avoid having to specify the fully ?ualified name when you use a class# $or e"ample, the (ystem namespace contains sev&eral classes, including Console# Console has a 'rite/ine method that, as you might e"pect, writes a line to the system console# *f you want to write the output part of a -ello 'orld program in C%, you can say1

&'ste(.)onso!e.*rite+ine(,-e!!o *or!"!,);

This same code can !e written as1

.sing &'ste(; )onso!e.*rite+ine(,-e!!o *or!"!,);

That's almost everything you need for the C% -ello 'orld program# 5 complete C% program needs a class definition and a Main function# 5 complete, console&!ased -ello 'orld program in C% looks like this1

using &'ste(;

c!ass -e!!o*or!" { /u$!ic static int 0ain(&tring12 args)

{ )onso!e.*rite+ine(,-e!!o3 *or!"!,); return 0; } }

The first line makes (ystem.the COM+ !ase class namespace.availa!le to the program# The program class itself is named -ello'orld =code is arranged into classes, not !y files># The Main method =which takes arguments> is defined within -ello'orld# The COM+ Console class writes the friendly message, and the program is finished# Of course, you could get fancy# 'hat if you want to reuse the -ello'orld program3 Aasy.put it into its own namespace6 Just wrap it in a namespace and declare the classes as pu!lic if you want them accessi!le outside the particular namespace# =Bote here that *'ve changed the name Main to the more suita!le name (ay-i#>

using &'ste(;

na(es/ace 0&450ag { /u$!ic c!ass -e!!o*or!" { /u$!ic static int &a'-i() { )onso!e.*rite+ine(,-e!!o3 *or!"!,); return 0; } } }

0ou can then compile this into a C//, and include the C// with any other programs you're !uilding# The calling program could look like this1

using &'ste(; using 0&450ag;

c!ass )a!!ing0&450ag {

/u$!ic static 6oi" 0ain(string12 args) { -e!!o*or!".&a'-i(); return 0; } }

One final point a!out classes# *f you have classes with the same name in more than one namespace, C% lets you define aliases for any of them so you don't have to fully ?ualify them# -ere's an e"ample# (uppose you have created a class B(@#B(D# Class5 that looks like this1

na(es/ace 5&1.5&2 { c!ass )!assA {} }

0ou can then create a second namespace, B(E, that derives the class BE#Class this1

from B(@#B(D#Class5 like

na(es/ace 5&7 { c!ass )!assB: 5&1.5&2.)!assA {} }

*f this construct is too long for you, or if you're going to repeat it several times, you can use the alias 5 for the class B(@#B(D#Class5 with the using statement like so1

na(es/ace 5&7 { using A = 5&1.5&2.)!assA; c!ass )!assB: A {} }

This effect can !e accomplished at any level of an o!2ect hierarchy# $or instance, you could also create an alias for B(@#B(D like this1

na(es/ace 5&7

{ using ) = 5&1.5&2; c!ass )!assB: ).A {} }

&odernity /ike coding languages, the needs of programmers evolve over time# 'hat was once revolutionary is now sort of, well, dated# /ike that old Toyota Corolla on the neigh!or's lawn, C and C++ provide relia!le transportation, !ut lack some of the features that people look for when they kick the tires# This is one of the reasons many developers have tinkered with the Java language over the past few years# C% goes !ack to the drawing !oard and emerges with several features that * longed for in C++# ,ar!age collection is one e"ample.everything gets cleaned up when it's no longer referenced# -owever, gar!age collection can have a price# *t makes pro!lems caused !y certain risky !ehavior =using unsafe casts and stray pointers, for e"ample> far harder to diagnose and potentially more devastating to a program# To compensate for this, C% implements type safety to ensure application sta!ility# Of course, type safety also makes your code more reada!le, so others on your team can see what you've !een up to .you take the !ad with the good, * guess# *'ll go into this later in this article# C% has a richer intrinsic model for error handling than C++# -ave you ever really gotten deep into a coworker's code3 *t's ama7ing.there are do7ens of unchecked -FA(8/Ts all over the place, and when a call fails, the program always ends up displaying an )Arror1 There was an error) message# C% improves on this situation !y providing integral support for throw, try###catch, and try###finally as language elements# True, you could do this as a macro in C++, !ut now it's availa!le right out of the !o"# Gart of a modern language is the a!ility to actually use it for something# *t seems simple enough, !ut many languages completely ignore the needs for financial and time&!ased data types# They're too old economy or something# orrowing from languages like (H/, C% implements !uilt&in support for data types like decimal and string, and lets you implement new primitive types that are as efficient as the e"isting ones# *'ll discuss some of the new support for data types and arrays later in the article# 0ou'll also !e glad to see that C% takes a more modern approach to de!ugging# The traditional way to write a de!ugga!le program in C++ was to sprinkle it with %ifdefs and indicate that large sections of code would only !e e"ecuted during the de!ugging process# 0ou would end up with two implementations.a de!ug !uild and a retail !uild, with some of the calls in the retail !uild going to functions that do nothing# C% offers the conditional keyword to control program flow !ased on defined tokens# Femem!er the M(CBMag namespace3 5 single conditional statement can make the (ay-i mem!er a de!ug&only function#

using &'ste(;

na(es/ace 0&450ag { /u$!ic c!ass -e!!o*or!" { 1con"itiona!(,48B.9,)2 /u$!ic static 6oi" &a'-i() { )onso!e.*rite+ine(,-e!!o3 *or!"!,); return;

} ::: } }

Conditional functions must have void return types =as *'ve set in this sample># The client program would then have to look like this to get a -ello 'orld message1

using &'ste( using 0&450ag

"efine 48B.9

c!ass )a!!ing0&450ag { /u$!ic static 6oi" 0ain(string12 args) { -e!!o*or!".&a'-i(); return 0; } }

The code is nice and uncluttered without all those %ifdefs hanging around, waiting to !e ignored# $inally, C% is designed to !e easy to parse, so vendors can create tools that allow source !rowsing and two&way code generation# O*+ect Oriented 0eah, yeah# C++ is o!2ect oriented# Fight# *'ve personally known people who have worked on multiple inheritance for a week, then retired out of frustration to Borth Carolina to clean hog lagoons# That's why C% ditches multiple inheritance in favor of native support for the COM+ virtual o!2ect system# Ancapsulation, polymorphism, and inheritance are preserved without all the pain# C% ditches the entire concept of glo!al functions, varia!les, and constants# *nstead, you can create static class mem!ers, making C% code easier to read and less prone to naming conflicts# 5nd speaking of naming conflicts, have you ever forgotten that you created a class mem!er and redefined it later on in your code3 y default, C% methods are nonvirtual, re?uiring an e"plicit virtual modifier# *t's far harder to accidentally override a method, it's easier to provide correct versioning, and the vta!le doesn't grow as ?uickly# Class mem!ers in C% can !e defined as private, protected, pu!lic, or internal# 0ou retain full control over their encapsulation# Methods and operators can !e overloaded in C%, using a synta" that's a lot easier than the one used !y C++# -owever, you can't overload glo!al operator functions.the overloading is strictly local in scope# The overloading of method $ !elow is an e"ample of what this looks like1

interface ;<est

{ 6oi" F(); 6oi" F(int >); 6oi" F(ref int >); 6oi" F(out int >); == F() == F(int) == F(ref int) == F(out int)

6oi" F(int >3 int '); == F(int3 int) int F(string s); int F(int >); } == F(string) == F(int)

The COM+ component model is supported through the implementation of delegates.the o!2ect&oriented e?uivalent of function pointers in C++# *nterfaces support multiple inheritance# Classes can privately implement internal interfaces through e"plicit mem!er implementations, without the consumer ever knowing a!out it# ,ype Safety 5lthough some power users would disagree with me, type safety promotes ro!ust programs# (everal features that promote proper code e"ecution =and more ro!ust programs> in Visual asic have !een included in C%# $or e"ample, all dynamically allocated o!2ects and arrays are initiali7ed to 7ero# 5lthough C% doesn't automatically initiali7e local varia!les, the compiler will warn you if you use one !efore you initiali7e it# 'hen you access an array, it is automatically range checked# 8nlike C and C++, you can't overwrite unallocated memory# *n C% you can't create an invalid reference# 5ll casts are re?uired to !e safe, and you can't cast !etween integer and reference types# ,ar!age collection in C% ensures that you don't leave references dangling around your code# -and&in&hand with this feature is overflow checking# 5rithmetic operations and conversions are not allowed if they overflow the target varia!le or o!2ect# Of course, there are some valid reasons to want a varia!le to overflow# *f you do, you can e"plicitly disa!le the checking# 5s *'ve mentioned, the data types supported in C% are somewhat different from what you might !e used to in C++# $or instance, the char type is @: !its# Certain useful types, like decimal and string, are !uilt in# Gerhaps the !iggest difference !etween C++ and C%, however, is the way C% handles arrays# C% arrays are managed types, meaning that they hold references, not values, and they're gar!age collected# 0ou can declare arrays in several ways, including as multidimensional =rectangular> arrays and as arrays of arrays =2agged># Bote in the following e"amples that the s?uare !rackets come after the type, not after the identifier as in some languages#

int1 2 intArra'; int1 3 3 2 intArra';

== A si(/!e arra' == A (u!ti"i(ensiona! arra' == of rank 7 (7 "i(ensions)

int1 21 2 intArra' int1 21 3 3 21 3 2 intArra';

== A ?agge" arra' of arra's == A sing!e@"i(ensiona! arra' == of three@"i(ensiona! arra's == of two@"i(ensiona! arra's

5rrays are actually o!2ectsI when you first declare them they don't have a si7e# $or this reason, you must create them after you declare them# (uppose you want an array of si7e J# This code will do the trick1

int12 intArra' = new int1A2;

*f you do this twice, it automatically reallocates the array# Therefore

int12 intArra'; intArra' = new int1A2; intArra' = new int1102;

results in an array called int5rray, which has @K mem!ers# *nstantiating a rectangular array is similarly easy1

int132 intArra' = new int173B2;

-owever, instantiating a 2agged array needs a !it more work# 0ou might e"pect to say new intLEML;M, !ut you really need to say1

int1212 intArra' = new int17212; For (int a = 0; a # intArra'.+ength; aCC) { intArra'1a2 = new intArra'1B2; }

0ou can initiali7e a statement in the same line you create and instantiate it !y using curly !rackets1

int12 intArra' = new int1A2 {13 23 73 B3 A};

0ou can do the same thing with a string&!ased array1

string12 strArra' = new string172 {,0&D,3 ,0;54,3,0&450ag,};

*f you mi" !rackets, you can initiali7e a multidimensional array1

int132 intArra' = new int173 22 { {13 2}3 {73 B}3 {A3 E} };

0ou can also initiali7e a 2agged array1

int1212 intArra' = new int1212 { new int12 {2373B}3 new int12 {A3E3F}

};

*f you leave out the new operator, you can even initiali7e an array with implicit dimensions1

int12 intArra' = {13 23 73 B3 A};

5rrays are considered o!2ects in C%, and as such they are handled like o!2ects, not like an addressa!le stream of !ytes# (pecifically, arrays are automatically gar!age collected, so you don't need to destroy them when you're finished using them# 5rrays are !ased on the C% class (ystem#5rray, so you can treat them conceptually like a collection o!2ect, using their /ength property and looping through each item in the array# *f you define int5rray as shown earlier, the call

intArra'.+ength

would return J# The (ystem#5rray class also provides ways to copy, sort, and search arrays# C% provides a foreach operator, which operates like its counterpart in Visual asic, letting you loop through an array# Consider this snippet1

int12 intArra' = {23 B3 E3 G3 103 @23 @73 @B3 G}; foreach (int i in intArra') { &'ste(.)onso!e.*rite+ine(i); }

This code will print each num!er in int5rray on its own line of the system console# The (ystem#5rray class also provides a ,et/ength mem!er function, so the preceding code could also !e written like this =remem!er, arrays are 7ero&!ased in C%>1

for (int i = 0; i # intArra'.9et+ength(); iCC) { &'ste(.)onso!e.*rite+ine(intArra'(i)); }

Scala*ility C and C++ re?uire all sorts of often&incompati!le header files !efore you can compile all !ut the simplest code# C% gets rid of these fre?uently aggravating headers !y com!ining the declaration and definition of types# *t also directly imports and emits COM+ metadata, making incremental compiles much easier# 'hen a pro2ect gets large enough, you might want to split up your code into smaller source files# C% doesn't have any restrictions a!out where your source files live or what they're named# 'hen you compile a C% pro2ect, you can think of it as concatenating all the source files, then compiling them into one !ig file# 0ou don't have to track which headers go where, or which routines !elong in which source file# This also means that you can move, rename, split, or merge source files without !reaking your compile# Version Support C// -ell is a constant pro!lem for users and programmers alike# M(CB+ Online has even dedicated a service specifically for users who need to track the different versions of system C//s# There's nothing a

programming language can do to keep a li!rary author from messing around with a pu!lished 5G*# -owever, C% was designed to make versioning far easier !y retaining !inary compati!ility with e"isting derived classes# 'hen you introduce a new mem!er in a !ase class as one that e"ists in a derived class, it doesn't cause an error# -owever, the designer of the class must indicate whether the method is meant as an override or as a new method that 2ust hides the similar inherited method# 5s *'ve already mentioned, C% works with a namespace model# Classes and interfaces in class li!raries must !e defined in hierarchical namespaces instead of in a flat model# 5pplications can e"plicitly import a single mem!er of a namespace, so there won't !e any collisions when multiple namespaces contain similarly named mem!ers# 'hen you declare a namespace, su!se?uent declarations are considered to !e part of the same declaration space# Therefore, if your code looks like this

na(es/ace 0&450ag.Artic!e { c!ass Author { ... } } na(es/ace 0&450ag.Artic!e { c!ass <o/ic { ... } }

you could e"press the same code like so1

na(es/ace 0&450ag.Artic!e { c!ass Author { ... }

c!ass <o/ic {

... } }

Compati*ility $our types of 5G*s are common on the 'indows platform and C% supports all of them# The old&style C 5G*s have integrated support in C%# 5pplications can use the BNCirect features of COM+ to call C&style 5G*s# C% provides transparent access to standard COM and O/A 5utomation 5G*s and supports all data types through the COM+ runtime# Most importantly, C% supports the COM+ Common /anguage (u!set specification# *f you've e"ported any entities that aren't accessi!le from another language, the compiler can optionally flag the code# $or instance, a class can't have two mem!ers runJo! and run2o! !ecause a case&insensitive language would choke on the definitions# 'hen you call a C// e"port, you need to declare the method, attach a sysimport attri!ute, and specify any custom marshaling and return value information that overrides the COM+ defaults# The following shows how to write a -ello 'orld program that displays its message of cheer in a standard 'indows message !o"#

c!ass -e!!o*or!" { 1s'si(/ort("!! = ,user72."!!,)2 /u$!ic static e>tern int 0essageBo>A(int h3 string (3 string c3 int t'/e);

/u$!ic static int 0ain() { return 0essageBo>A(03 ,-e!!o *or!"!,3 ,)a/tion,3 0); } }

Aach COM+ type maps to a default native data type, which COM+ uses to marshal values across a native 5G* call# The C% string value maps to the /G(TF type !y default, !ut it can !e overridden with marshaling statements like so1

using &'ste(; using &'ste(.;ntero/;

c!ass -e!!o*or!" { 1"!!i(/ort(,user72."!!,)2 /u$!ic static e>tern int 0essageBo>*(

int h3 1(arsha!(.n(anage"<'/e.+H*&tr)2 string (3 1(arsha!(.n(anage"<'/e.+H*&tr)2 string c3 int t'/e);

/u$!ic static int 0ain() { return 0essageBo>*(03 ,-e!!o *or!"!,3 ,)a/tion,3 0); } }

*n addition to working with C// e"ports, you can work with classic COM o!2ects in several ways1 create them with CoCreate*nstance, ?uery them for interfaces, and call methods on them# *f you want to import a COM class definition for use within your program, you must take two steps# $irst, you must create a class and use the comimport attri!ute to mark it as related to a specific ,8*C# The class you create can't have any !ase classes or interface lists, nor can it have any mem!ers#

== "ec!are Fi!gra/h0anager as a )I0 c!assic coc!ass 1co(i(/ort3 gui"(,8B7E8BB7@A2BF@11)8@JFA7@0020AF0BAFF0,)2 c!ass Fi!gra/h0anager { }

5fter the class is declared in your program, you can create a new instance of it with the new keyword =which is e?uivalent to the CoCreate*nstance function>#

c!ass 0ain)!ass { /u$!ic static 6oi" 0ain() { Fi!gra/h0anager f = new Fi!gra/h0anager(); } }

0ou can ?uery interfaces indirectly in C% !y attempting to cast an o!2ect to a new interface# *f the cast fails, it will throw a (ystem#*nvalidCastA"ception# *f it works, you'll have an o!2ect that represents that interface#

Fi!gra/h0anager gra/h0anager = new Fi!gra/h0anager(); ;0e"ia)ontro! (c = (;0e"ia)ontro!) gra/h0anager; (c.Kun(); == ;f the cast succee"s3 this !ine wi!! work.

-le.i*ility *t's true that C% and COM+ create a managed, type&safe environment# -owever, it's also true that some real&world applications need to get to the native code level.either for performance considerations or to use old&style, unmoderni7ed 5G*s from other programs# *'ve discussed ways to use 5G*s and COM components from your C% program# C% lets you declare unsafe classes and methods that contain pointers, structs, and static arrays# These methods won't !e type&safe, !ut they will e"ecute within the managed space so you don't have to marshal !oundaries !etween safe and unsafe code# These unsafe features are integrated with the COM+ AA and code access security in COM+# This means that a developer can pin an o!2ect so that the gar!age collector will pass over them when it's doing its work# =(ort of like a me7u7ah for your code#> 8nsafe code won't !e e"ecuted outside a fully trusted environment# Grogrammers can even turn off gar!age collection while an unsafe method is e"ecuting# ' aila*ility C% was announced in June and will !e part of the upcoming Visual (tudio #BAT suite# 5 compiler is e"pected to !e availa!le later this year, in advance of the release of the ne"t generation of Visual (tudio+# -or related articles see: The $uture of Visual asic1 'e! $orms, 'e! (ervices, and /anguage Anhancements (lated for Be"t ,eneration -or *ac/ground information see: O!2ect&oriented (oftware Made (imple with COM+ Funtime (ervices The COM+ Grogramming Model Makes it Aasy to 'rite Com&ponents in 5ny /anguage

is the technical editor for MSDN Magazine# -e has written numerous articles for MSJ and MIND, the predecessors to MSDN Magazine, as well as a !ook, Hoop Stats: The Basketball Abstract#
0oshua ,rupin

You might also like