Differences between C++ and C#
C# is a distinct language from C++. C++ is designed for general object
oriented programming in the days when the typical computer was a standalone
machine running a command line-based user interface, C# is designed
specifically to work with the .Net and is geared to the modern environment of
Windows and mouse-controlled user interface, networks and the internet.
Microsoft has defined C# as follows:
"C# is a simple, modern, object oriented, and
type-safe programming language derived from C and C++. C# (pronounced 'C
sharp') is firmly planted in the C and C++ family tree of languages, and will
immediately be familiar to C and C++ programmers. C# aims to combine the high
productivity of Visual Basic and the raw power of C++."
However it is also undeniable that the two languages are very similar in
both their syntax and in that they are both designed to facilitate the same
paradigm of programming, in which code is based around hierarchies of inherited
classes.
Below I will briefly summarize the overall differences and similarities
between the two languages. If you are a C++ programmer, these points will give
you the most important differences between the two languages at a glance.
- Environment
C++ was designed to be a low-level platform-neutral object-oriented
programming language. C# was designed to be a somewhat higher-level
component-oriented language. The move to a managed environment represents
a sea change in the way you think about programming. C# is about letting
go of precise control, and letting the framework help you focus on the big
picture.
With the managed environment of .NET, you give up that level of control.
When you choose the type of your object, the choice of where the object
will be created is implicit. Simple types (int, double, and long) are
always created on the stack (unless they are contained within other
objects), and classes are always created on the heap. You cannot control
where on the heap an object is created, you can't get its address, and you
can't pin it down in a particular memory location. (There are ways around
these restrictions, but they take you out of the mainstream.)
The very structure of C# reflects the underlying framework. There are no
multiple inheritances and there are no templates because multiple
inheritances are terribly difficult to implement efficiently in a managed,
garbage-collected environment, and because generics have not been
implemented in the framework.
- Compile
Target
C++ code usually compiles to assembly language. C# by contrast compiles to
Intermediate language (IL), which has some similarities to java byte code.
The IL is subsequently converted to native executable code by a process of
Just-In-Time compilation. The emitted IL code is stored in a file or a set
of files known as an assembly. An assembly essentially forms the unit, in
which IL code id packaged, corresponding to a DLL, or executable file that
would be created by C++ compiler.
- Memory
Management
C# is designed to free the developers from
the bookkeeping tasks to do with the memory management. That means in C#
you do not have to explicitly delete memory that was allocated dynamically
on the heap, as you could in C++. Rather, the garbage collector
periodically cleans up memory that is no longer needed.
Lets have two C++ variable declarations
int j
= 30;
Myclass
*pMine=new Myclass
Here the contents of j are stored on the stack. This is exactly that
exists with C# value types. Our Myclass instance is, however stored on the
heap, and the pointer to it is on the stack. This is basically the
situation with C# reference type, except that in C# the syntax dresses the
pointer up as a reference. The equivalent of C# is:
Int j=30;
Myclass
mine=new Myclass()
This code has pretty much the same effect in terms of where the objects
are stored as does the above C++ code - the difference is that Myclass is
syntactically treated as a reference rather then a pointer.
The big difference between C++ and C# is that
C# doesn't allow you to choose how to allocate memory for a particular
instance. For example, in C++ you wished to do this:
Int*
pj=new int(30);
Myclass
Mine; dfd
This will cause the int to be allocated on the heap, and the Myclass
instance to be allocated on the stack. You can't do this in C# because C#
deems that an int is a value type while any class is always a reference
type.
The other difference is that there is no equivalent to C++'s delete
operator in C#. Instead, with C#, the .Net garbage collector periodically
comes in and scans through the refrences in your code in order to identify
which areas of the heap are currently in use by our program. It is then
automatically able to remove all the objects that are no longer in use.
This technique effectively saves you from having to free up nay memory
yourself on the heap.
- Program
Flow
Program flow is similar in C# to C++. In particular, the following
statements works exactly the same way as they do in C++ and have the same
syntax :
For, Return, Goto,
Break, Continue
New in
C# :
foreach
There are couple of syntactical differences
for the if, while, do...while and switch
statements and C# provides an additional control flow statement; foreach
- If …. Else Condition
if statement works exactly the same way and has exactly the same syntax in
C# as in C++, apart from one point. The condition in each if and else
clause must evaluate to a bool. For example, assuming x is an integer data
types, not a bool, the following C++ code would generate a compilation
error in C#
if(x)
{ … }
The correct syantax in C#
If(x != 0)
{ … }
This shows that how additionally type safety in C# traps error early.
While and do …while
Int x;
While(x) //wrong
While(x != 0) //OK
Just as for if, these statements have exactly syntax and purpose in C# as
they do in C++, except that the condition expression must evaluate to a
bool.
- Switch
the switch statement server the same purposes in C# as it does in C++. It
is however; more powerful in C# since you can use a string as the test variables,
something that is not possible in C++.
In C# a switch statement may not "fall through" to the next
statement if it does any work. Thus, while the following is legal in C++,
it is not legal in C#:
switch (i)
{
case 4:
CallFuncOne();
case 5: // error, no fall through
CallSomeFunc();
}
To accomplish this, you need to use an explicit goto statement:
switch (i)
{
case 4:CallFuncOne();
goto case 5;
case 5:
CallSomeFunc();
}
If the case statement does not work (has no code within it) then you can
fall through:
switch (i)
{
case 4: // fall through
case 5: // fall through
case 6:
CallSomeFunc();
}
- New
control flow statement- “foreach”
C# provides an additional flow control statement, foreach. Foreach loops
across all items in array or collection without requiring explicit
specification of the indices.
Syntax:
Foreach(double
someElement in MyArray)
{
Console.WriteLine(someElement);
}
- Boxing
In some cases you might wish to treat a value type as if it was a refrence
type. This is achived by a process know as boxing.
Syntactically this just means casting the variable to an object.
Int j = 10;
Object boxobj = (object) j;
Boxing acts like any other cast, but you should be aware that it means the
contents of the variables will be copies to the heap and a reference
created.
The usual reason for boxing a value in order to pass it to a method that
expects a erfrence type as a parameter. You can also unbox value, simply
by casting it back to its original type.
Int j = 10;
Object boxobj = (object) j;
Int k = (int) boxobj;
The process of unboxing will raise an exception if you attempt to cast to
the wrong type and no cast is available for you to do the conversion.
- Structs
Structs are significantly different in C#. In C++ a struct is exactly like
a class, except that the default inheritance and default access are public
rather than private. In C# structs are very different from classes.
Structs in C# are designed to encapsulate lightweight objects. They are
value types (not reference types), so they're passed by value. In
addition, they have limitations that do not apply to classes. For example,
they are sealed, which means they cannot be derived from or have any base
class other than System.ValueType, which is derived from Object. Structs
cannot declare a default (parameter less) constructor.
- Value
Types and reference types
C# distinguishes between value types and reference types. Simple types
(int, long, double, and so on) and structs are value types, while all
classes are reference types, as are Objects. Value types hold their value
on the stack, like variables in C++, unless they are embedded within a
reference type. Reference type variables sit on the stack, but they hold
the address of an object on the heap, much like pointers in C++. Value
types are passed to methods by value (a copy is made), while reference
types are effectively passed by reference.
- Classes
Classes in C# follow much the same principles as in C++, though there are
a few differences in both features and syntax.
Class MyClass : MyBaseClass
{
Private string SomeFiels;
Public in SomeMethod()
{
Return 2;
}
}
Classes defined in C# using what at first sight looks like much the same
syntax as in C++, but there are numerous differences:
- There is
no access modifier on the name of the base class. Inheritance is always
public
- A class
can only be derived from one base class. If no base class is explicitly
specified, then the class will automatically be derived from
System.Object, which will give the class all the functionality of
System.Object, the most commnly used of which is ToString().
- In C++,
the only types of class members are variables, functions, constructors,
destructors and operator overloads, C# also permits delegates, events and
properties.
- The
access modifiers public, private and protected have the same meaning as
in C++ but there are two additional access modifiers available:
i.
Internal
ii.
Protected internal
- C++
requires a semicolon after the closing brace at the end of a class
definition. This is not required in C#.
- Destructors
C# implements a very different programming model for destructors to
C++.This is because the garbage collection mechanism in C# implies that:
- There is
less need for destructors, since dynamically allocated memory will get
removed automatically.
- Since it
is not possible to predict when the garbage collector will actually
destroy a given object, if you do supply a destructor for a class, it is
not possible to predict precisely when that destructor will be executed.
Because memory is cleaned up behind the
scenes of C#, you will find that only a
small proportion of your classes actually require destructors. C# has two-stage
destruction mechanism:
- The class
should derive from IDisposable interface and implements Dispose ()
method.
- The class
should separately implements at destructor, which is viewed as a reserve
mechanism in case a client doesn't need to call Dispose()
C#'s destructor looks, syntactically
much like a C++ destructor, but it is totally
different. The C# destructor is simply a shortcut for declaring a Finalize
method that chain up to its base class. Thus writing
~MyClass()
{
// do work here
}
is identical to writing
MyClass.Finalize()
{
// do work here
base.Finalize();
}
- Virtual
methods must be explicitly overridden
In C# the programmer's decision to override a virtual method must be made
explicit with the override keyword.
To see why this is useful, assume that a Window class is written by
Company A, and that List Box and Radio Button classes were written by
programmers from Company B using a purchased copy of the Company A Window
class as a base. The programmers in Company B have little or no control
over the design of the Window class, including future changes that Company
A might choose to make.
Now suppose that one of the programmers for Company B decides to add a
Sort method to ListBox:
public class ListBox
: Window
{
public virtual void Sort()
{"}
}
This presents no problems until Company A, the author of Window, releases
version 2 of its Window class. It turns out that the programmers in
Company A also added a Sort method public class Window:
public class Window
{
// "
public virtual void Sort()
{"}
}
In C++ the new virtual Sort method in Windows would now act as a base
method for the virtual Sort method in ListBox. The compiler would call the
Sort method in ListBox when you intend to call the Sort in Window. In C# a
virtual function is always considered to be the root of virtual dispatch, that
is, once C# finds a virtual method, it looks no further up the inheritance
hierarchy If a new virtual Sort function is introduced into Window the
run-time behavior of ListBox is unchanged. When ListBox is compiled again,
however, the compiler generates a warning:
"\class1.cs(54,24): warning CS0114: 'ListBox.Sort()' hides inherited
member 'Window.Sort()'.
To make the current member override that implementation, add the override
keyword. Otherwise add the new keyword.
To remove the warning, the programmer must indicate what he intends. He
can mark the ListBox Sort method new, to indicate that it is not an
override of the virtual method in Window:
public class ListBox
: Window
{
public new virtual void Sort()
{"}
}
This action removes the warning. If, on the other hand, the programmer
does want to override the method in Window, he need only use the override
keyword to make that intention explicit.
- C#
requires definite assignment
C# requires definite assignment, which means that the local variables, age,
ID, and yearsServed must be initialized before you call GetStats. This is
unnecessarily cumbersome; you're just using them to get values out of
GetStats. To address this problem, C# also provides the out keyword, which
indicates that you may pass in uninitialized variables and they will be
passed by reference. This is a way of stating your intentions explicitly:
public class MyClass
{
public void GetStats(out int
age, out int ID, out int yearsServed) { ….. }
}
Again, the calling method must match.
MyClass.GetStats(out
age,out ID, out yearsServed);
- Boolean
Values Conversion
There is no conversion between the bool type and other types (specifically
int).
C# Boolean values can not be treated as integer
If you write a code like this
if(BoolReturnFunction()) {}
and check if it returns zero it will evaluate flase and otherwise true
However using assignment versus equality is not allowed ,if you write:
if( x = 4 ) {}
Where x is Boolean type variable, it will give you an compile error
Constant value '4' cannot be converted to a 'bool'
If you write like this:
if(Convert.ToInt32(x)=4)
{}
it will give you compilation error
Cannot implicitly convert type 'int' to 'bool'
- Exceptions
Exceptions are used in the same way in C# as in C++, apart from the
following two differences:
- C#
defines the finally block, which contains code that is always executed at
the end of try block irrespective of whether any exception was thrown.
The lack of this feature in C++ has been a common cause of complaint
among C++ developers. The finally block is executed as soon as control
leaves a catch or try block, and typically contains cleanup code for
resources allocated in the try block.
- In C++,
the class thrown in the exception may be any class. C#, however, requires
that the exception be a class derived from System.Exception.
C++ syntax for catch:
Catch (…) {}
C# syntax for catch:
Catch { }
The full syntax fro try..catch..finally in C# looks like this
Try {}
Catch (MyException e) {}
Finally {}
- Delegates-
Substitute of Pointer
C# does not support function pointers. However a similar effect is
achieved by wrapping references to methods in special forms of class know
as delegates.
A delegate is a class that can hold a reference to a method. Unlike other
classes, a delegate class has a signature, and it can hold references only
to methods that match its signature. A delegate is thus equivalent to a
type-safe function pointer or a callback.
Delegates can be passed around between methods, and used to call the
methods to which they contains reference, in the same way that function
pointers can be in C++. Conceptually delegates can be used in a similar
way to an interface with a single method. The main practical difference is
that with an interface the method name is fixed, whereas with a delegate
only the signature is fixed - the method name can be different
// delegate
declaration
delegate void MyDelegate(int i);
class Program
{
public static void Main()
{
TakesADelegate(new
MyDelegate(DelegateFunction));
}
public static void
TakesADelegate(MyDelegate SomeFunction)
{
SomeFunction(21);
}
public static void
DelegateFunction(int i)
{
System.Console.WriteLine("Called by delegate with number:
{0}.", i);
}
}
Output: Called by delegate with number: 21.
- Properties
Most C++ programmers try to keep member variables private. This data
hiding promotes encapsulation and allows you to change your implementation
of the class without breaking the interface your clients rely on. You
typically want to allow the client to get and possibly set the value of
these members, however, so C++ programmers create accessor methods whose
job is to modify the value of the private member variables.
In C#, properties are first-class members of classes. To the client, a
property looks like a member variable, but to the implementor of the class
it looks like a method. This arrangement is perfect; it allows you total
encapsulation and data hiding while giving your clients easy access to the
members.
Properties are defined with property declarations. The first part of a
property declaration resembles a field declaration. The second part
includes a Get accessor and/or a Set accessor. In the example below, a
class Employee defines a property Age.
public class Employee
{
private static int age;
public int Age
{
get{ return age;
}
set {age=
value;}
}
}
- Attributes
and Metadata.
One significant difference between C# and C++ is that C# provides inherent
support for metadata: data about your classes, objects, methods, and so
forth. Attributes come in two flavors: those that are supplied as part of
the CLR and attribute you create for your own purposes. CLR attributes are
used to support serialization, marshaling, and COM interoperability. A
search of the CLR reveals a great many attributes. As you've seen, some
attributes are applied to an assembly, others to a class or interface.
These are called the attribute targets.
Attributes are applied to their target by placing them in square brackets
immediately before the target item. Attributes may be combined, either by
stacking one on top of another.
[assembly:
AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile(".\\keyFile.snk")]
or by separating the attributes with commas.
[assembly:
AssemblyDelaySign(false),
assembly:
AssemblyKeyFile(".\\keyFile.snk")]
Custom Attributes - Custom attributes are user-defined attributes that
provide additional information about program elements. For example, you
might define a custom security attribute that specifies the permissions
required by the caller to execute a procedure.
[AttributeUsage(AttributeTargets.All)]
public class DeveloperAttribute : System.Attribute
{
private string name;
public DeveloperAttribute(string name)
{
this.name =
name;
}
public virtual string
Name
{
get {return
name;}
}
}
You can apply this attribute in the following way:
[Developer("Joan
Smith")]
Conclusion
While there are a number of subtle traps waiting for the unwary C++
programmer, the syntax of C# is not very different from C++ and the
transition to the new language is fairly easy. The interesting part of
working with C# is working your way through the new common language
runtime library, which provides a host of functionality that previously
had to be written by hand. This article could only touch on a few
highlights. The CLR and the .NET Framework provide extensive support for
threading, marshaling, Web application development, Windows-based
application development, and so forth.
The distinction between language features and CLR features is a bit blurry
at times, but the combination is a very powerful development tool.
© ITGateway Solutions Private
Limited – IT Services Provider