| ||
|
| ||
C++ to C# - Making the JumpBy Linda NaughtonThis tutorial provides an introduction to C# intended for C++ programmers.
IntroductionThis tutorial is geared towards C# as used in the .NET Framework 2.0. It was written as a set of talking points for a presentation, so it is not very verbose.All information is provided without warranty, express or implied. What is C#?C++ meets Java meets VBGarbage collection and memory management Strings and lists .NET Framework - queues, XML, sockets, and all sorts of other utilities Visual Studio .NET Designer - rapid GUI design Variables and TypesValue Types – int, float, char, string, etc.Reference Types – objects No Pointers
C++ Way:
SampleObject mySampleObject; // Instantiates a copy
mySampleObject.SetName("Foo"); // OK
C# Way:
** Wrong: **
SampleObject mySampleObject; // Creates a REFERENCE
mySampleObject.SetName("Foo"); // NULL pointer exception
** Correct: **
SampleObject mySampleObject = new SampleObject();
mySampleObject.SetName("Foo");
Even value types are objects with useful functions:
string myString = "Hello world.";
if (myString.Contains("Hello")) { … }
int myInt = Integer.Parse("123");
float myFloat = 12.34;
Console.WriteLine("Value: " + myFloat.ToString());
Methods can pass back objects as references, but be careful!
class SampleObjectMgr
{
SampleObject m_currentSampleObject = new SampleObject("Foo");
// Returns a reference to the REAL current SampleObject
SampleObject GetCurrentSampleObject()
{
return m_currentSampleObject;
}
}
// This will actually CHANGE SampleObjectMgr's SampleObject
SampleObject myProt = SampleObjectMgr.GetCurrentSampleObject();
myProt.SetName("Bar");
A better (safer) way:
class SampleObjectMgr
{
SampleObject m_currentSampleObject = new SampleObject("Foo");
// Return a COPY of the SampleObject
SampleObject GetCurrentSampleObject()
{
return new SampleObject(m_currentSampleObject);
}
}
Memory ManagementCreation is done using 'new'.Deletion/cleanup is done automatically when a variable goes out of scope. (Most of the time, anyway)
void DoSomething() {
SampleObject obj = new SampleObject();
...
// obj is auto-scheduled for garbage collection
}
If the object is passed to another function that stores a reference to it, C# is smart enough to not delete it so long as someone is referencing it.
Exception: Objects that implement the "Dispose" method use “unmanaged” resources. Must call Dispose manually when you're done with it.
void DrawBorder() {
Pen myPen = new Pen(Color.Black);
...
// Pen class implements Dispose, so call it
myPen.Dispose();
}
EnumsStrongly typed.
enum VehicleType
{
Car,
Truck,
Motorcycle
}
VehicleType type = VehicleType.Car;
Can be converted to and from strings.
VehicleType vehicleType = VehicleType.Car;
file.Write(vehicleType.ToString());
string vehicleTypeString = “Car”;
VehicleType vehicleType =
(VehicleType) Enum.Parse(typeof(VehicleType),
vehicleTypeString
Can also get a list of names in the enum:
string[] vehicleTypeNames =
Enum.GetNames(typeof(VehicleType));
Arrays and Lists (Collections)Raw arrays are not recommended (in most cases), though they exist.
string[] myStrings = new string[2];
myStrings[0] = "ABC";
myStrings[1] = "DEF";
Console.WriteLine(myStrings[0]);
Better to use a List collection.
List<string> myStringList = new List<string>();
myStringList.Add("ABC");
myStringList.Add("DEF");
int numItems = myStringList.Count;
Console.WriteLine(myStringList[0]);
Various types of lists exist:
SortedList
Dictionary
Etc.
Lists can store any object type.
List<string> stringList = new List<string>(); List<int> intList = new List<string>(); List<Vehicle> vehicleList = new List<Vehicle>(); LoopsStandard loops exist: for, while, etc.Also new: foreach
foreach(string myString in myStringList)
{ Console.WriteLine(myString); }
ExceptionsSome are issued automatically.
// Will issue null pointer exception
SampleObject mySampleObject;
mySampleObject.SetName("foo");
// Will issue a parsing exception
Integer.Parse("ABC");
Can also issue them on demand.
if (myValue > 174)
{ throw new Exception("The value is too big! " + myValue); }
Can also issue custom exception types with custom arguments.
throw new SampleObjectException(SampleObjectError.BadName);
Exception Handling:Uses try/catch blocks
void Bar()
{
try
{
Foo();
}
catch // Catches ALL exceptions thrown by Foo
{
MessageBox.Show(“Error with Foo.”);
}
// Because the catch statement didn't shut down the
// app or return or anything, execution will
// continue from here after the message box.
DoSomethingElse();
}
Can catch only specific exceptions if you want:
void Bar()
{
try
{
Foo();
}
// Catch only parsing and socket exceptions.
catch (ParsingException)
{
MessageBox.Show(“Error parsing foo data.”);
}
catch (SocketException)
{
socket.Close();
}
DoSomethingElse();
}
Unhandled exceptions filter “up” to the calling routine, and up and up and up until finally if nobody has handled the exception, the App crashes with the standard windows “FooApplication has suffered an unexpected error and must be closed” message box.
ClassesSame general rules as C++No Header Files
public class SampleObject
{
string m_name;
List
Inheritance is also the same:
public class ChildSampleObject : SampleObject { … }
Visibility is mostly the same:
public
protected
private
internal (public within namespace; private elsewhere)
Default for members: private
Default for methods: internal Partial classes may be spread across multiple files.
// In SampleObject.cs
public partial class SampleObject { … }
// In SampleObject.Designer.cs
public partial class SampleObject { … }
// In SampleObject.Events.cs
public partial class SampleObject { … }
PropertiesNew class feature: PropertiesIdeal for get/set members
C++ way:
string m_name;
public void SetName(string name) { … };
public string GetName() { … };
C# way:
string m_name;
public string Name
{
get { return m_name; }
// Set uses the special "value" parameter
set { m_name = value; }
}
InterfacesNew class feature: InterfacesIdeal for classes that just need to expose an interface, and don't need to inherit data or methods from a base class.
interface ISerializable
{
void Serialize();
void Deserialize();
}
class Message : ISerializable
{
void Serialize() { … }
void Deserialize() { … }
}
A class can implement multiple interfaces, but can only have one parent class:
class ChildSampleObject: ISerializable,
IComparable, SampleObject {}
Namespaces and UsingAll classes must belong to a namespace.
In SampleObject.cs:
namespace Sample
{
class SampleObject { … }
}
In ContentItem.cs:
namespace Sample
{
class ContentItem { … }
}
You can also create sub-namespaces:
namespace Sample.Test { … }
You must 'use' a namespace before you can call things in it. Common .NET utilities exist in the “System” namespace (though there are others).
using System.Collections;
using Injector.SampleObject;
Events and DelegatesThere's a built-in method for issuing and handling asynchronous events.1. Define the event, event handler prototype (delegate), and event handlers
2. Receivers subscribe to the event so the Sender knows they want it
3. Sender issues the event, calling the subscribers' event handlers
ThreadsUsed for multi-threading.
StatusMgr()
{
Thread m_updateThread = new Thread(StatusUpdateThread);
m_updateThread.IsBackground = true;
m_updateThread.Start();
}
void StatusUpdateThread()
{
…
Thread.Sleep(STATUS_UPDATE_TIME);
}
Thread safety: Built-in semaphores with lock and/or monitor
class Test
{
object m_padlock = new Object();
int m_testValue = 0;
public TestValue
{
get
{
lock (m_padlock)
{ return m_testValue; }
}
set
{
lock (m_padlock)
{ m_testValue = value; }
}
}
void TestThead()
{
lock (m_padlock)
{
m_testValue++;
}
}
}
Monitor works the same as lock, but has an Enter and Exit method, and a TryEnter with timeout:
if (Monitor.TryEnter(m_padlock, TIMEOUT_MS)
{
m_testValue++;
Monitor.Exit(m_padlock);
}
else
{
// handle timeout error
}
C# is smart enough not to deadlock if you lock again from within the same thread.
Threads, Events and Invoke.NET Thread Model:There is no queue. The event handler is called directly by Thread2 just like a normal method. MUST WORRY ABOUT THREAD SAFETY!
You can use "Invoke" or "BeginInvoke" to hold off processing of the event until Thread1 runs.
Sample invoke code:
if (InvokeRequired)
{
Invoke(
(MethodInvoker)delegate()
{
ProcessStatusChange();
}
);
}
else
{
ProcessStatusChange();
}
Note:
| ||
|
All content copyright 1996-2008 by Linda Naughton O'Meara unless otherwise noted.
Shadowrun is a copyright and trademark of WizKids, LLC.
Earthdawn is a copyright and trademark of FASA Corporation.
Crimson Skies is a copyright and trademark of Microsoft Corporation.
Babylon 5 is a copyright and trademark of Time Warner Entertainment.
Battlestar Galactica is a copyright of Sci Fi / Universal.
Any use of characters, names, places, etc. from these systems is done with the greatest respect for their creators, and is not intended as a challenge to any copyrights or trademarks.
| ||