C++ is regarded as a mid-level language. This indicates that C++ comprises a combination of both high-level and low-level language features. 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 andC++. 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.
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 task of doing memory management. It 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++ delete operator in C#. Instead, withC#, 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# : for each
(1) 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 syntax 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.
(2) Switch
The switch statement serve 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 inC++.
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
switch (i)
{
case 4: // fall through
case 5: // fall through
case 6:
CallSomeFunc();
}
(3) New control flow statement- for each
C# provides an additional flow control statement, for each. For each loops across all items in array or collection without requiring explicit specification of the indices.
Syntax:
Foreach(double someElement in MyArray)
{
Console.WriteLine(someElement);
}
(4) Boxing
In some cases you might wish to treat a value type as if it was a reference type. This is achieved 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 reference 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.
(5) 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.
(6) 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.
(7) 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;
}
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#.
(8) 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# 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();
}
(9) 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.
(10) 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);
(11) 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 false 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'
(12) 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 {}
(13) 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.
(14) 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 implementer 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);
}
}
(15) 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);
}
}
Conclusion
While there are a number of subtle traps waiting for the unwary C++ programmer, the syntax ofC# 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.