Shadowing vs Hiding vs Overriding
In C#, it is easy to confuse hiding with overriding. Both are ways to change the implementation of elements from a base class. But there are some significant differences between the two.
A further confusion steps in with the term shadowing. Shadowing is a VB concept. In C#, this concept is called hiding, though there is a subtle difference between these two terms.
- For VB.NET, shadowing is element name dependent, and hides ALL the elements in the base class regardless of signature. So a base class with an element called "Hello()" with ten different signatures would all be shadowed by a derived class.
- For C#.NET, hiding is signature dependent. So the new keyword would only be applied to the specific element with the same signature. In this case, only the particular "Hello()" element with exactly the same signature would be hidden, and the remaining nine "Hello()"s would not be affected.
Hence, we use both shadowing and hiding to provide new implementations to the base class without overriding it. That is, the access level, return type, and the signature of the derived class elements which are shadowed, may differ from the base class. However, when hiding in C#, the access level, the signature, return type of the derived class must be same as the base class. Otherwise, there's nothing to hide.
Now, back to the technical differences between hiding and overriding.
(1) New is reference-type specific, overriding is object-type specific.
In simple terms, hiding allows you to implement the "reference signature" in a new manner, and keeps the original implementation (ie. two versions of the same signature can be accessed from outside classes). Overriding on the other hand, rewrites the "reference signature" (ie. only one version of the signature can be accessed from outside classes). However, two signatures are physically present in memory for both overriding and hiding.
Hence, if base.Hello() is overridden by child.Hello(), then only child.Hello() is seen by outside classes. Using new however, allows both base.Hello() and child.Hello() to be viewed by outside classes, depending on the run-time typecast. Below is a code example of what I meant.
The illustrated code can be downloaded here [code demo].
First, we implement the base class "Foo", and "Bar" is the derived class. "Xnew" represents the hidden property, whereas "Xovr" represents the overridden property. In addition, "BaseXnew" and "BaseXovr" represent the physical references to the properties in the "Foo" parent class. An instance "bar" is created from the derived class and its properties are printed out in the console.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | class Foo { public virtual string Xnew { get { return "parent"; } } public virtual string Xovr { get { return "parent"; } } } class Bar : Foo { public new string Xnew { get { return "child"; } } public override string Xovr { get { return "child"; } } internal string BaseXnew { get { return base.Xnew; } } internal string BaseXovr { get { return base.Xovr; } } } static void Main(string[] args) { Bar bar = new Bar(); Console.WriteLine(((Foo)bar).Xnew); Console.WriteLine(((Foo)bar).Xovr); Console.WriteLine(bar.Xnew); Console.WriteLine(bar.Xovr); Console.WriteLine(bar.BaseXnew); Console.WriteLine(bar.BaseXovr); } |
-------------------- Console print outs -------------------- ((Foo)bar).Xnew = parent** <-- Old property is used ((Foo)bar).Xovr = child** <-- New property is used bar.Xnew = child <-- New property is used bar.Xovr = child <-- New property is used bar.BaseXnew = parent <-- base.Old property is accessible bar.BaseXovr = parent <-- base.Old property is accessible
Here, you can see that when bar is of type "Bar", the child implementations are used for both overriding and hiding. However, when bar is type-casted to its parent class "Foo", the parent implementation that was originally hidden by the new keyword is now used. On the other hand, override still uses the child implementation.
(2) The parent class is ignorant of what is new
With new, the parent class cannot enforce or prohibit hiding. Basically, it assumes no knowledge that its children will try to replace some of its parts. So there is no need to pre-declare virtual in the parent to implement a new method. However, to override a base class element, the parent class must self-declare that element as overridable to avoid its children from replacing its significant parts.
As such, the new keyword allows for changes in the access level of the element. So if the base element was "internal", then the new element can use any other access levels. Overriding however is access level specific because the parent knows the parts that could get replaced.
Knowing the above differences should be enough to get you started. More details can be found at http://msdn.microsoft.com/en-us/library/ms172785%28VS.80%29.aspx
Print This PostWhen to use a Dictionary (Hashtable)?
Here's a pretty good tutorial on hashtable / dictionaries. Found it while studying some performance issues between the use of try/catch vs contains key for a dictionary with about 200,000 key/value associations.
A Dictionary is closely related to a HashTable. There are many subtle differences between them, but one important difference is that a Dictionary is generally faster than a Hashtable for storing data.
The reason is that a Dictionary takes strongly-typed values as its input, so you do not suffer the performance impact of storing generic Objects and boxing/unboxing them into the proper types during use.
http://www.kirupa.com/net/dictionary_hashtable.htm
Print This PostMulti-threading in C#
Threading is fun, because with it you can do a lot more stuff at the same time. For example, keeping your UI updated while your background tasks are running.
C# supports parallel execution of code through multi-threading. A thread is an independent execution path, able to run simultaneously with other threads. Here, we examine three simple C# approaches to help your application perform multiple tasks simultaneously.
- Method 1: Using System.Thread (easy but unsafe, for low risk use)
- Method 2: Using Application.DoEvents (okay for general purposes)
- Method 3: Using BackgroundWorker class (preferred for thread safety)
Of the three methods listed above, the method 1 is the easiest, but is considered unsafe. However, I still find it useful as a quick-n-dirty implementation for rapid prototyping developing, running simulations or testing out new algorithms. It also provides for simple pause and resume mechanisms.
Download: Demo using System.Threading.
Method 2 is an event-driven approach that applies asynchronous event handlers, and then calls Application.DoEvents to repaint the UI. Hence, its more like multi-tasking rather than multi-threading. In addition, it has a slight re-entry flaw supposed inherited from its predecessors.
Download: Demo using Application.DoEvents.
For now, it seems like method 3 is the generally accepted preferred practice using thread-safe methods. Its a bit more tedious to implement neatly. I have included source code to provide a short framework to illustrate its capabilities.
Download: Demo using BackgroundWorker.
Method 1: Using System.Threading (easy)
Using System.Threading for threading purposes is bad. The class exposes two dangerous methods Suspend() and Resume() that are considered unsafe, and are given deprecated warnings since .NET 2.0. However, I still find it useful as a quick-n-dirty implementation for rapid prototyping developing, running simulations or testing out new algorithms. It also provides for simple pause and resume mechanisms. Simplest approach if you need to show a prototype to your client quickly.
Nevertheless, its important to understand that its major problem is that of deadlocks. You have no way of knowing what code a thread is executing when you suspend it. If you suspend a thread while it holds locks during a security permission evaluation, other threads in the AppDomain might be blocked. If you suspend a thread while it is executing a class constructor, other threads in the AppDomain that attempt to use that class are blocked. Deadlocks can occur very easily. Here's an example of a program exhibiting deadlock: http://www.yoda.arachsys.com/csharp/threads/deadlocks.shtml
So at any point in time, the thread could be doing anything. Executing suspend stops the thread running in its tracks. Suspended. Hence, imagine your thread is reading a file and places a lock on it. You suspend your thread. File stays locked. Same goes for any other resources.
Anyway, if you need a quick solution, here is an outline of how the demo source above works. The UI object starts a new thread for the task object. Hence the UI object and the task object run on separate threads. The task object then performs the endless loop. On each iteration, the task object has to perform an invoke to update the UI object on a cross-thread. Thats it, easy.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | class MainForm { // ... void StartThread(object sender, EventArgs e) { // creates the new thread and starts it _thread = new Thread(new ThreadStart(DoThreadTask)); _thread.Start(); } // creates the task object and runs it void DoThreadTask() { WorkTask task = new WorkTask(); task.StartEndlessLoop(this); } // invoked by the task object to update the UI internal void RefreshForm(int i) { txtSomeText.Text = i.ToString(); } } class WorkTask { internal void StartEndlessLoop(MainForm caller) { // ... caller.Invoke((MethodInvoker)delegate() { // when we get here we are now in the context // of the primary user interface thread, hence // we can modify all of it's controls caller.RefreshForm(i); }); } } |
Method 2: Using Application.DoEvents (okay)
To start, lets quickly run through what Application.DoEvents() actually does. From the framework, each time the form handles an event, it processes all the code associated with that event. All other events wait in a queue. While your code handles the event, your application does not respond. For example, the window does not repaint if another window is dragged on top.
If you call DoEvents in your code, your application will somewhat interrupt your code and handle the other events. For example, if you have a form that adds data to a ListBox and add DoEvents to your code, your form repaints when another window is dragged over it. If you remove DoEvents from your code, your form will not repaint until the click event handler of the button is finished executing.
With reference to the demo source code above, we first create an EventArgs object that basically stores the UI update data. So this EventArgs dutifully carries data from the task object to the UI object in each iteration.
Before the UI starts running the task, it pre-determines the updates that need that to be done by adding a new event to the task through AddEndCycleEvent. Note that Application.DoEvent is supposed to be called at the end the pre-determined set of updates to redraw the UI.
Finally, at the end of every iteration in the task object, it calls OnEndCycle(), which sends the EventArgs object back to the UI through the EventHandler.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | // EventArgs to store your update data class NubcakeEventArgs : EventArgs { // ... } class MainForm { // ... void StartRunning(object sender, EventArgs e) { _task.AddEndCycleEvent(new NubcakeEventHandler( delegate(object nbSender, NubcakeEventArgs nbEvent) { // ... do all your UI stuff here. Application.DoEvents(); })); _task.StartEndlessLoop(); } } class WorkTask { event NubcakeEventHandler _endCycleEvent; readonly NubcakeEventArgs _eventArgs = new NubcakeEventArgs(); internal void StartEndlessLoop() { // ... while (i > -1) { // ... do task OnEndCycle(i++); // ... check to exit } } internal void AddEndCycleEvent(NubcakeEventHandler nbEvent) { _endCycleEvent += nbEvent; } void OnEndCycle(int val) { if (_endCycleEvent != null) { _endCycleEvent(this, _eventArgs.Update(val)); } } } |
Again, this method is very simple to use. But here's the catch. The DoEvent method has a re-entry problem: Calling Application.DoEvents can cause code to be re-entered or re-performed if a message raises an event. In other words, this approach is not exactly multi-threading, but rather multi-tasking by switching to process event to event in the queue. Rightfully, long running tasks should be running in another thread, then we marshal calls to update the UI back to the UI thread. So DoEvents is considered a hacky solution to this problem because:
Application.DoEvents is taken straight from Delphis, and the same re-entry problem has been known for like 15 years now - Michael Starberg
(http://www.techtalkz.com/c-c-sharp/83924-application-doevents.html)
Instead, we next look at the .NET 2.0 BackgroundWorker class, which is pretty much better designed for such things. And here's how its done.
Method 3: Using BackgroundWorker class (preferred)
Using the BackgroundWorker class is a multi-threading approach. Following the demo source code available at the top of this page, there are four main parts to this approach.
- WorkState is used to store the current working status of the task. It also stores the relevant data that will be used for updating the UI
- NubcakeWorker extends from BackgroundWorker, and this is the multi-threading processor. It contains three important event handlers namely DoWork, ProgressChanged, and RunWorkerCompleted. DoWork basically handles the event that starts the looping task, ProgressChanged handles the callback per iteration, and RunWorkerCompleted handles the event when the looping task ends or is terminated.
- MainForm is the UI that we want to update, and it contains two important methods. One is PerformTask that is invoked when a user clicks a start button. And the second is RefreshState that updates the UI, and it is called by the ProgressChanged method in NubcakeWorker per iteration.
- WorkTask is the task manager that performs the set of long running tasks. You can then update the UI by calling the worker.ReportProgress() function that invokes the ProgressChanged method to update the UI via RefreshState. That is ReportProgress -> ProgressChanged -> RefreshState -> UI updated.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | class WorkState { internal WorkState Start() { // Start state } internal WorkState Update() { // Update state } internal WorkState Cancel() { // Cancel state } internal WorkState End() { // End state } } class NubcakeWorker : BackgroundWorker { // Starts the INubCaketask with the endlessloop new void DoWork(object sender, DoWorkEventArgs e) { // ... e.Result = ((INubcakeTask)e.Argument).Start(worker); } // Invoked when a progress update is required new void ProgressChanged(object sender, ProgressChangedEventArgs e) { // ... // Param e.UserState contains a WorkState object that // contains all the UI update information. _parent.RefreshState(e.ProgressPercentage, e.UserState); } // Invoked when the task is completed or cancelled. new void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { _parent.CompletedTasks((bool)e.Result); } } class MainForm : Form, INubcakeForm { readonly INubcakeTask _task; // WorkTask readonly BackgroundWorker _worker; // BackgroundWorker void PerformTask(object sender, EventArgs e) { // starts the task. Calls event _worker.DoWork(); _worker.RunWorkerAsync(_task); } public void RefreshState(int progressPercentage, object userState) { // ... do the UI updates } } class WorkTask : INubcakeTask { public bool Start(BackgroundWorker worker) // i.e. NubcakeWorker { worker.ReportProgress(0, _state.Start()); while loop { // ... do task worker.ReportProgress(100, _state.Update()); // ... if cancelled, then report cancelled. } worker.ReportProgress(100, _state.End()); } } |
As you can see, BackgroundWorker needs a bit more work to get right. But once you get the hang of it, its a pretty neat way to separate your tasks from your UI. And, AFAIK its the encouraged practice. Personally, I think all the methods work. It really depends on your project requirements and risks.
Anyway, generally multi-threading or multi-tasking can help improve the responsiveness of the program, and CPU prioritization can also benefit application performance. However, don't forget that threading has some computational switching costs. So if there are TOO many threads, then each thread may not be given enough time to execute much during its time slice. So, do use these approaches in moderation.
Print This Post